├── .changeset ├── README.md └── config.json ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── renovate.json └── workflows │ ├── gh-pages.yml │ ├── publish-each-pr.yml │ ├── publish.yml │ ├── release.yml │ ├── sync-gitee.yml │ └── test.yml ├── .gitignore ├── .npmrc ├── .prettierrc.js ├── .vscode └── settings.json ├── .yarnrc ├── LICENSE ├── README.md ├── algolia └── docsearch.json ├── babel.config.js ├── example ├── .expo-shared │ └── assets.json ├── .gitignore ├── App.tsx ├── app.json ├── assets │ ├── adaptive-icon.png │ ├── favicon.png │ ├── icon.png │ └── splash.png ├── babel.config.js ├── metro.config.js ├── package.json ├── src │ ├── GlobalContext.ts │ ├── components │ │ ├── DemoBlock │ │ │ └── index.tsx │ │ └── index.ts │ ├── index.tsx │ ├── navigation │ │ ├── Layout.tsx │ │ ├── index.tsx │ │ └── routes.ts │ ├── pages │ │ ├── actionBar │ │ │ └── index.tsx │ │ ├── actionSheet │ │ │ └── index.tsx │ │ ├── badge │ │ │ └── index.tsx │ │ ├── button │ │ │ └── index.tsx │ │ ├── calendar │ │ │ ├── CalendarSingle.tsx │ │ │ └── index.tsx │ │ ├── cell │ │ │ └── index.tsx │ │ ├── checkbox │ │ │ └── index.tsx │ │ ├── circle │ │ │ └── index.tsx │ │ ├── collapse │ │ │ └── index.tsx │ │ ├── config-provider │ │ │ └── index.tsx │ │ ├── dateTimePicker │ │ │ └── index.tsx │ │ ├── dialog │ │ │ └── index.tsx │ │ ├── divider │ │ │ └── index.tsx │ │ ├── empty │ │ │ └── index.tsx │ │ ├── field │ │ │ └── index.tsx │ │ ├── form │ │ │ ├── Base.tsx │ │ │ ├── List.tsx │ │ │ ├── Rules.tsx │ │ │ ├── Subscribe.tsx │ │ │ ├── Type.tsx │ │ │ └── index.tsx │ │ ├── grid │ │ │ └── index.tsx │ │ ├── icon │ │ │ ├── icons.ts │ │ │ └── index.tsx │ │ ├── image-picker │ │ │ └── index.tsx │ │ ├── image-preview │ │ │ └── index.tsx │ │ ├── image │ │ │ └── index.tsx │ │ ├── index-bar │ │ │ └── index.tsx │ │ ├── index.tsx │ │ ├── input │ │ │ └── index.tsx │ │ ├── layout │ │ │ └── index.tsx │ │ ├── loading │ │ │ └── index.tsx │ │ ├── navbar │ │ │ └── index.tsx │ │ ├── notice-bar │ │ │ └── index.tsx │ │ ├── notify │ │ │ └── index.tsx │ │ ├── number-keyboard │ │ │ └── index.tsx │ │ ├── overlay │ │ │ └── index.tsx │ │ ├── panningViews │ │ │ └── index.tsx │ │ ├── picker │ │ │ └── index.tsx │ │ ├── popover │ │ │ └── index.tsx │ │ ├── popup │ │ │ └── index.tsx │ │ ├── progress │ │ │ └── index.tsx │ │ ├── radio │ │ │ └── index.tsx │ │ ├── rate │ │ │ └── index.tsx │ │ ├── search │ │ │ └── index.tsx │ │ ├── selector │ │ │ └── index.tsx │ │ ├── slider │ │ │ └── index.tsx │ │ ├── stepper │ │ │ └── index.tsx │ │ ├── swipeCell │ │ │ └── index.tsx │ │ ├── swiper │ │ │ └── index.tsx │ │ ├── switch │ │ │ └── index.tsx │ │ ├── tab │ │ │ └── index.tsx │ │ ├── tag │ │ │ └── index.tsx │ │ ├── toast │ │ │ └── index.tsx │ │ ├── transitions │ │ │ └── index.tsx │ │ └── typography │ │ │ └── index.tsx │ ├── style │ │ └── vars.ts │ └── utils │ │ ├── iframeMessage.ts │ │ └── index.ts ├── tsconfig.json ├── web │ └── index.html ├── webpack.config.js └── yarn.lock ├── jest.config.js ├── jest └── setup.js ├── lerna.json ├── package.json ├── packages ├── dumi-theme-vant │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ └── src │ │ ├── builtins │ │ ├── SourceCode.less │ │ ├── SourceCode.tsx │ │ └── Table.tsx │ │ ├── components │ │ ├── Container │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── Header │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── Nav │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── SearchInput │ │ │ ├── index.less │ │ │ └── index.tsx │ │ └── Simulator │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── hooks │ │ ├── index.ts │ │ ├── useColor.ts │ │ ├── useHandlePostPath.ts │ │ ├── useMeta.ts │ │ └── useThemeConfig.ts │ │ ├── interface.ts │ │ ├── layout.tsx │ │ ├── pages │ │ ├── index.ts │ │ └── rerender │ │ │ └── index.tsx │ │ ├── style │ │ ├── base.less │ │ ├── font.less │ │ ├── highlight.less │ │ ├── layout.less │ │ └── var.less │ │ └── utils │ │ ├── iframeMessageSwap.ts │ │ ├── index.ts │ │ └── scrollDoc.ts ├── rn-vant-icons │ ├── CHANGELOG.md │ ├── README.md │ ├── iconfont.json │ ├── package.json │ ├── src │ │ ├── Add.tsx │ │ ├── AddO.tsx │ │ ├── AddSquare.tsx │ │ ├── AfterSale.tsx │ │ ├── Aim.tsx │ │ ├── Alipay.tsx │ │ ├── AppsO.tsx │ │ ├── Arrow.tsx │ │ ├── ArrowDown.tsx │ │ ├── ArrowLeft.tsx │ │ ├── ArrowUp.tsx │ │ ├── Ascending.tsx │ │ ├── Audio.tsx │ │ ├── Award.tsx │ │ ├── AwardO.tsx │ │ ├── BackTop.tsx │ │ ├── Bag.tsx │ │ ├── BagO.tsx │ │ ├── BalanceList.tsx │ │ ├── BalanceListO.tsx │ │ ├── BalanceO.tsx │ │ ├── BalancePay.tsx │ │ ├── BarChartO.tsx │ │ ├── Bars.tsx │ │ ├── Bell.tsx │ │ ├── Bill.tsx │ │ ├── BillO.tsx │ │ ├── BirthdayCakeO.tsx │ │ ├── Bookmark.tsx │ │ ├── BookmarkO.tsx │ │ ├── BrowsingHistory.tsx │ │ ├── BrowsingHistoryO.tsx │ │ ├── BrushO.tsx │ │ ├── BulbO.tsx │ │ ├── BullhornO.tsx │ │ ├── CalendarO.tsx │ │ ├── Card.tsx │ │ ├── Cart.tsx │ │ ├── CartCircle.tsx │ │ ├── CartCircleO.tsx │ │ ├── CartO.tsx │ │ ├── CashBackRecord.tsx │ │ ├── CashOnDeliver.tsx │ │ ├── CashierO.tsx │ │ ├── Certificate.tsx │ │ ├── ChartTrendingO.tsx │ │ ├── Chat.tsx │ │ ├── ChatO.tsx │ │ ├── Checked.tsx │ │ ├── Circle.tsx │ │ ├── Clear.tsx │ │ ├── Clock.tsx │ │ ├── ClockO.tsx │ │ ├── Close.tsx │ │ ├── ClosedEye.tsx │ │ ├── Cluster.tsx │ │ ├── ClusterO.tsx │ │ ├── Column.tsx │ │ ├── Comment.tsx │ │ ├── CommentCircle.tsx │ │ ├── CommentCircleO.tsx │ │ ├── CommentO.tsx │ │ ├── Completed.tsx │ │ ├── Contact.tsx │ │ ├── Coupon.tsx │ │ ├── CouponO.tsx │ │ ├── CreditPay.tsx │ │ ├── Cross.tsx │ │ ├── DebitPay.tsx │ │ ├── Delete.tsx │ │ ├── DeleteO.tsx │ │ ├── Descending.tsx │ │ ├── Description.tsx │ │ ├── DesktopO.tsx │ │ ├── Diamond.tsx │ │ ├── DiamondO.tsx │ │ ├── Discount.tsx │ │ ├── Down.tsx │ │ ├── EcardPay.tsx │ │ ├── Edit.tsx │ │ ├── Ellipsis.tsx │ │ ├── Enlarge.tsx │ │ ├── EnvelopO.tsx │ │ ├── Exchange.tsx │ │ ├── Expand.tsx │ │ ├── ExpandO.tsx │ │ ├── Eye.tsx │ │ ├── EyeO.tsx │ │ ├── Fail.tsx │ │ ├── Failure.tsx │ │ ├── FilterO.tsx │ │ ├── Fire.tsx │ │ ├── FireO.tsx │ │ ├── FlagO.tsx │ │ ├── FlowerO.tsx │ │ ├── Font.tsx │ │ ├── FontO.tsx │ │ ├── FreePostage.tsx │ │ ├── Friends.tsx │ │ ├── FriendsO.tsx │ │ ├── Gem.tsx │ │ ├── GemO.tsx │ │ ├── Gift.tsx │ │ ├── GiftCard.tsx │ │ ├── GiftCardO.tsx │ │ ├── GiftO.tsx │ │ ├── GoldCoin.tsx │ │ ├── GoldCoinO.tsx │ │ ├── GoodJob.tsx │ │ ├── GoodJobO.tsx │ │ ├── GoodsCollect.tsx │ │ ├── GoodsCollectO.tsx │ │ ├── Graphic.tsx │ │ ├── GuideO.tsx │ │ ├── HomeO.tsx │ │ ├── Hot.tsx │ │ ├── HotO.tsx │ │ ├── HotSale.tsx │ │ ├── HotSaleO.tsx │ │ ├── HotelO.tsx │ │ ├── Idcard.tsx │ │ ├── Info.tsx │ │ ├── InfoO.tsx │ │ ├── Invitation.tsx │ │ ├── Label.tsx │ │ ├── LabelO.tsx │ │ ├── Like.tsx │ │ ├── LikeO.tsx │ │ ├── Live.tsx │ │ ├── Location.tsx │ │ ├── LocationO.tsx │ │ ├── Lock.tsx │ │ ├── Logistics.tsx │ │ ├── Manager.tsx │ │ ├── ManagerO.tsx │ │ ├── MapMarked.tsx │ │ ├── Medal.tsx │ │ ├── MedalO.tsx │ │ ├── Minus.tsx │ │ ├── More.tsx │ │ ├── MoreO.tsx │ │ ├── Music.tsx │ │ ├── MusicO.tsx │ │ ├── New.tsx │ │ ├── NewArrival.tsx │ │ ├── NewArrivalO.tsx │ │ ├── NewO.tsx │ │ ├── NewspaperO.tsx │ │ ├── NotesO.tsx │ │ ├── OrdersO.tsx │ │ ├── OtherPay.tsx │ │ ├── Paid.tsx │ │ ├── Passed.tsx │ │ ├── Pause.tsx │ │ ├── PauseCircle.tsx │ │ ├── PauseCircleO.tsx │ │ ├── PeerPay.tsx │ │ ├── PendingPayment.tsx │ │ ├── Phone.tsx │ │ ├── PhoneCircle.tsx │ │ ├── PhoneCircleO.tsx │ │ ├── PhoneO.tsx │ │ ├── Photo.tsx │ │ ├── PhotoFail.tsx │ │ ├── PhotoO.tsx │ │ ├── Photograph.tsx │ │ ├── Play.tsx │ │ ├── PlayCircle.tsx │ │ ├── PlayCircleO.tsx │ │ ├── Plus.tsx │ │ ├── PointGift.tsx │ │ ├── PointGiftO.tsx │ │ ├── Points.tsx │ │ ├── Printer.tsx │ │ ├── Qr.tsx │ │ ├── QrInvalid.tsx │ │ ├── Question.tsx │ │ ├── QuestionO.tsx │ │ ├── Records.tsx │ │ ├── RefundO.tsx │ │ ├── Replay.tsx │ │ ├── Revoke.tsx │ │ ├── Scan.tsx │ │ ├── Search.tsx │ │ ├── SendGift.tsx │ │ ├── SendGiftO.tsx │ │ ├── Service.tsx │ │ ├── ServiceO.tsx │ │ ├── Setting.tsx │ │ ├── SettingO.tsx │ │ ├── Share.tsx │ │ ├── ShareO.tsx │ │ ├── ShieldO.tsx │ │ ├── Shop.tsx │ │ ├── ShopCollect.tsx │ │ ├── ShopCollectO.tsx │ │ ├── ShopO.tsx │ │ ├── ShoppingCart.tsx │ │ ├── ShoppingCartO.tsx │ │ ├── Shrink.tsx │ │ ├── Sign.tsx │ │ ├── Smile.tsx │ │ ├── SmileComment.tsx │ │ ├── SmileCommentO.tsx │ │ ├── SmileO.tsx │ │ ├── Sort.tsx │ │ ├── Star.tsx │ │ ├── StarO.tsx │ │ ├── Stop.tsx │ │ ├── StopCircle.tsx │ │ ├── StopCircleO.tsx │ │ ├── Success.tsx │ │ ├── ThumbCircle.tsx │ │ ├── ThumbCircleO.tsx │ │ ├── TodoList.tsx │ │ ├── TodoListO.tsx │ │ ├── Tosend.tsx │ │ ├── TvO.tsx │ │ ├── UmbrellaCircle.tsx │ │ ├── Underway.tsx │ │ ├── UnderwayO.tsx │ │ ├── Upgrade.tsx │ │ ├── UserCircleO.tsx │ │ ├── UserO.tsx │ │ ├── Video.tsx │ │ ├── VideoO.tsx │ │ ├── VipCard.tsx │ │ ├── VipCardO.tsx │ │ ├── Volume.tsx │ │ ├── VolumeO.tsx │ │ ├── WapHome.tsx │ │ ├── WapHomeO.tsx │ │ ├── WapNav.tsx │ │ ├── WarnO.tsx │ │ ├── Warning.tsx │ │ ├── WarningO.tsx │ │ ├── WeappNav.tsx │ │ ├── Wechat.tsx │ │ ├── WechatPay.tsx │ │ ├── YouzanShield.tsx │ │ ├── helper.ts │ │ └── index.tsx │ ├── tsconfig.build.json │ └── tsconfig.json └── rn-vant │ ├── .umirc.ts │ ├── CHANGELOG.md │ ├── README.md │ ├── docs │ ├── CHANGELOG.md │ ├── get-started.md │ ├── home.md │ └── icon.md │ ├── package.json │ ├── src │ ├── ActionBar │ │ ├── ActionBar.tsx │ │ ├── ActionBarButton.tsx │ │ ├── ActionBarContext.ts │ │ ├── ActionBarIcon.tsx │ │ ├── index.md │ │ ├── index.tsx │ │ ├── style.ts │ │ └── type.ts │ ├── ActionSheet │ │ ├── ActionSheet.tsx │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Badge │ │ ├── Badge.tsx │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Button │ │ ├── Button.tsx │ │ ├── README.md │ │ ├── __tests__ │ │ │ ├── Button.test.tsx │ │ │ └── __snapshots__ │ │ │ │ └── Button.test.tsx.snap │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Calendar │ │ ├── Calendar.tsx │ │ ├── CalendarDay.tsx │ │ ├── CalendarHeader.tsx │ │ ├── CalendarMonth.tsx │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ ├── type.ts │ │ └── utils.ts │ ├── Cell │ │ ├── Cell.tsx │ │ ├── CellGroup.tsx │ │ ├── index.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Checkbox │ │ ├── Checkbox.tsx │ │ ├── Group.tsx │ │ ├── content.ts │ │ ├── index.md │ │ ├── index.style.ts │ │ └── index.ts │ ├── Circle │ │ ├── Circle.tsx │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Collapse │ │ ├── Collapse.tsx │ │ ├── CollapseItem.tsx │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── ConfigProvider │ │ ├── ConfigProvider.tsx │ │ ├── ConfigProviderContext.ts │ │ ├── README.md │ │ ├── index.tsx │ │ └── type.ts │ ├── Dash │ │ ├── Dash.tsx │ │ ├── index.ts │ │ ├── interface.ts │ │ ├── measureMeHOC.tsx │ │ └── util.ts │ ├── DatetimePicker │ │ ├── DatePicker.tsx │ │ ├── DatetimePicker.tsx │ │ ├── README.md │ │ ├── TimePicker.tsx │ │ ├── index.ts │ │ ├── type.ts │ │ ├── useDateState.ts │ │ └── utils.ts │ ├── Dialog │ │ ├── Dialog.tsx │ │ ├── index.md │ │ ├── index.tsx │ │ ├── style.ts │ │ └── type.ts │ ├── Divider │ │ ├── Divider.tsx │ │ ├── index.md │ │ ├── index.ts │ │ ├── interface.ts │ │ └── style.ts │ ├── Empty │ │ ├── Empty.tsx │ │ ├── Images.tsx │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Field │ │ ├── Field.tsx │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Form │ │ ├── Form.tsx │ │ ├── FormContext.tsx │ │ ├── FormItem.tsx │ │ ├── FormList.tsx │ │ ├── FormSubscribe.tsx │ │ ├── README.md │ │ ├── index.ts │ │ └── type.ts │ ├── Grid │ │ ├── Grid.tsx │ │ ├── GridItem.tsx │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Image │ │ ├── Image.tsx │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── ImagePicker │ │ ├── ImageItem.tsx │ │ ├── ImagePicker.tsx │ │ ├── README.md │ │ ├── Uploader.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ └── types.ts │ ├── ImagePreview │ │ ├── ImagePreview.tsx │ │ ├── README.md │ │ ├── index.tsx │ │ ├── style.ts │ │ └── type.ts │ ├── IndexBar │ │ ├── IndexAnchor.tsx │ │ ├── IndexBar.tsx │ │ ├── IndexBarContext.ts │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── types.ts │ ├── Input │ │ ├── BaseInput.tsx │ │ ├── Input.tsx │ │ ├── README.md │ │ ├── TextArea.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── KeyboardSpace │ │ ├── KeyboardSpace.tsx │ │ └── index.ts │ ├── Layout │ │ ├── Col.tsx │ │ ├── Row.tsx │ │ ├── RowContext.ts │ │ ├── index.md │ │ └── index.ts │ ├── LinearGradient │ │ ├── LinearGradient.tsx │ │ ├── index.ts │ │ └── types.ts │ ├── Loading │ │ ├── Circular.tsx │ │ ├── Loading.tsx │ │ ├── README.md │ │ ├── Spinner.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── NavBar │ │ ├── NavBar.tsx │ │ ├── index.md │ │ ├── index.ts │ │ ├── interface.ts │ │ └── style.ts │ ├── NoticeBar │ │ ├── Marquee.tsx │ │ ├── NoticeBar.tsx │ │ ├── index.md │ │ ├── index.ts │ │ ├── interface.ts │ │ └── style.ts │ ├── Notify │ │ ├── Notify.tsx │ │ ├── README.md │ │ ├── index.tsx │ │ ├── style.ts │ │ └── type.ts │ ├── NumberKeyboard │ │ ├── NumberKeyboard.tsx │ │ ├── NumberKeyboardKey.tsx │ │ ├── README.md │ │ ├── SlideAnimatable.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ └── types.ts │ ├── Overlay │ │ ├── Overlay.tsx │ │ ├── index.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── PanningViews │ │ ├── PanDismissibleView.tsx │ │ ├── PanGestureView.tsx │ │ ├── PanListenerView.tsx │ │ ├── PanResponderView.tsx │ │ ├── PanningContext.ts │ │ ├── PanningProvider.tsx │ │ ├── asPanViewConsumer.tsx │ │ └── index.ts │ ├── PasswordInput │ │ ├── PasswordInput.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ └── types.ts │ ├── Picker │ │ ├── Picker.tsx │ │ ├── README.md │ │ ├── WheelPicker.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ ├── type.ts │ │ └── utils.ts │ ├── Popover │ │ ├── Popover.tsx │ │ ├── README.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Popup │ │ ├── Dialog.tsx │ │ ├── DismissibleView.tsx │ │ ├── Popup.tsx │ │ ├── index.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Portal │ │ └── index.tsx │ ├── Progress │ │ ├── Progress.tsx │ │ ├── index.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Radio │ │ ├── Group.tsx │ │ ├── Radio.tsx │ │ ├── context.ts │ │ ├── index.md │ │ ├── index.style.ts │ │ └── index.ts │ ├── Rate │ │ ├── Rate.tsx │ │ ├── index.md │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Search │ │ ├── README.md │ │ ├── Search.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ └── types.ts │ ├── Selector │ │ ├── CheckMark.tsx │ │ ├── README.md │ │ ├── Selector.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Slider │ │ ├── README.md │ │ ├── Slider.tsx │ │ ├── index.tsx │ │ ├── style.ts │ │ └── types.ts │ ├── Space │ │ ├── Space.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Stepper │ │ ├── README.md │ │ ├── StepButton.tsx │ │ ├── Stepper.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── SwipeCell │ │ ├── README.md │ │ ├── SwipeCell.tsx │ │ ├── index.ts │ │ └── type.ts │ ├── Swiper │ │ ├── README.md │ │ ├── Swiper.tsx │ │ ├── SwiperItem.tsx │ │ ├── index.ts │ │ ├── style.ts │ │ └── type.ts │ ├── Switch │ │ ├── Switch.tsx │ │ ├── index.md │ │ ├── index.ts │ │ ├── interface.ts │ │ └── style.ts │ ├── Tabs │ │ ├── TabPane.tsx │ │ ├── Tabs.tsx │ │ ├── TabsBar.tsx │ │ ├── TabsContent.tsx │ │ ├── TabsContext.ts │ │ ├── index.md │ │ ├── index.ts │ │ ├── style.ts │ │ ├── type.ts │ │ ├── useScrollItem.ts │ │ └── utils.ts │ ├── Tag │ │ ├── Tag.tsx │ │ ├── index.md │ │ ├── index.tsx │ │ ├── interface.ts │ │ └── style.ts │ ├── Theme │ │ └── index.tsx │ ├── Toast │ │ ├── Toast.tsx │ │ ├── index.md │ │ ├── index.tsx │ │ ├── style.ts │ │ └── type.ts │ ├── TouchableOpacity │ │ ├── index.tsx │ │ └── type.ts │ ├── TouchableRipple │ │ ├── TouchableRipple.tsx │ │ └── index.ts │ ├── Transitions │ │ ├── Fade.tsx │ │ ├── ScaleFade.tsx │ │ ├── Slide.tsx │ │ ├── SlideFade.tsx │ │ ├── Stagger.tsx │ │ ├── Transition.tsx │ │ ├── index.ts │ │ └── types.ts │ ├── Typography │ │ ├── Typography.tsx │ │ ├── index.md │ │ ├── index.tsx │ │ ├── style.ts │ │ └── type.ts │ ├── Uploader │ │ └── type.ts │ ├── View │ │ ├── index.tsx │ │ └── type.ts │ ├── hooks │ │ ├── index.ts │ │ ├── useAnimatedValue.ts │ │ ├── useAnimatedValueArray.ts │ │ ├── useControllableValue.ts │ │ ├── useDestroyed.ts │ │ ├── useLayout.tsx │ │ ├── useLazyRef.ts │ │ ├── useLazyRender.ts │ │ ├── useMemoizedFn.ts │ │ ├── useOrientation.ts │ │ ├── useRefState.ts │ │ ├── useRefs.ts │ │ ├── useScrollTo.ts │ │ ├── useSetState.ts │ │ ├── useUnmountedRef.ts │ │ ├── useUpdate.ts │ │ └── useUpdateEffect.ts │ ├── index.ts │ ├── locale │ │ ├── index.ts │ │ └── lang │ │ │ ├── base.ts │ │ │ ├── en-US.ts │ │ │ ├── fr-FR.ts │ │ │ ├── ja-JP.ts │ │ │ ├── types.ts │ │ │ ├── zh-CN.ts │ │ │ ├── zh-HK.ts │ │ │ └── zh-TW.ts │ ├── styles │ │ ├── darkTheme.ts │ │ ├── defaultTheme.ts │ │ ├── index.ts │ │ ├── shadow.tsx │ │ ├── shortHand.ts │ │ └── variables.ts │ ├── tests │ │ └── shared │ │ │ └── snapshotTest.tsx │ ├── types.ts │ └── utils │ │ ├── cloneReactNode.ts │ │ ├── constants.ts │ │ ├── createUpdateEffect.ts │ │ ├── deepAssign.ts │ │ ├── devLog.ts │ │ ├── getContrastingColor.ts │ │ ├── getShortHand.ts │ │ ├── isDev.ts │ │ ├── isIcon.ts │ │ ├── isString.ts │ │ ├── number.ts │ │ ├── typeof.ts │ │ └── validate.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── scripts ├── bootstrap.js └── verify-commit-msg.js ├── tsconfig.base.json └── yarn.lock /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { 6 | "repo": "bijinfeng/rn-vant" 7 | } 8 | ], 9 | "commit": false, 10 | "fixed": [], 11 | "linked": [], 12 | "access": "public", 13 | "baseBranch": "master", 14 | "updateInternalDependencies": "patch", 15 | "ignore": [] 16 | } 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | indent_style = space 9 | indent_size = 2 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | 18 | [*.gradle] 19 | indent_size = 4 20 | 21 | [BUCK] 22 | indent_size = 4 23 | 24 | # Windows files 25 | [*.bat] 26 | end_of_line = crlf -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | web-build/ 3 | lib/ 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@youngjuning/eslint-config/react-native'], 3 | rules: { 4 | 'react-native/no-raw-text': 'off', 5 | 'import/no-cycle': 'off', 6 | 'react/require-default-props': 'off', 7 | 'no-param-reassign': 'off', 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "ignorePaths": ["**/example/**"] 4 | } -------------------------------------------------------------------------------- /.github/workflows/publish-each-pr.yml: -------------------------------------------------------------------------------- 1 | name: Expo Preview 2 | on: [pull_request] 3 | jobs: 4 | preview: 5 | runs-on: ubuntu-latest 6 | permissions: 7 | pull-requests: write # Allow comments on PRs 8 | steps: 9 | - name: 🏗 Setup repo 10 | uses: actions/checkout@v2 11 | 12 | - name: 🏗 Setup Node 13 | uses: actions/setup-node@v2 14 | with: 15 | node-version: 16.x 16 | cache: yarn 17 | 18 | - name: 🏗 Setup Expo 19 | uses: expo/expo-github-action@v7 20 | with: 21 | expo-version: latest 22 | token: ${{ secrets.EXPO_TOKEN }} 23 | 24 | - name: 📦 Install dependencies 25 | run: yarn bootstrap 26 | 27 | - name: 🚀 Publish to Expo 28 | working-directory: ./example 29 | run: expo publish --release-channel=pr-${{ github.event.number }} --non-interactive 30 | 31 | - name: 💬 Comment preview 32 | uses: expo/expo-github-action/preview-comment@v7 33 | with: 34 | channel: pr-${{ github.event.number }} 35 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Expo Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master # default branch 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: 🏗 Setup repo 13 | uses: actions/checkout@v2 14 | 15 | - name: 🏗 Setup Node 16 | uses: actions/setup-node@v3 17 | with: 18 | node-version: 16.x 19 | cache: yarn 20 | 21 | - name: 🏗 Setup Expo and EAS 22 | uses: expo/expo-github-action@v7 23 | with: 24 | expo-version: latest 25 | eas-version: latest 26 | token: ${{ secrets.EXPO_TOKEN }} 27 | 28 | - name: 📦 Install dependencies 29 | run: yarn bootstrap 30 | 31 | - name: 🚀 Publish Expo app 32 | working-directory: ./example 33 | run: expo publish 34 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | concurrency: ${{ github.workflow }}-${{ github.ref }} 9 | 10 | jobs: 11 | release: 12 | name: Release 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout Repo 16 | uses: actions/checkout@v3 17 | 18 | - name: Setup Node.js 16 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: 16 22 | 23 | - name: Install Dependencies 24 | run: yarn 25 | 26 | - name: Build Package 27 | run: yarn build 28 | 29 | - name: Create Release Pull Request 30 | uses: changesets/action@v1 31 | with: 32 | version: yarn ci:version 33 | commit: "chore: update versions" 34 | title: "chore: update versions" 35 | publish: yarn ci:publish 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 38 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 39 | -------------------------------------------------------------------------------- /.github/workflows/sync-gitee.yml: -------------------------------------------------------------------------------- 1 | name: Sync to Gitee 2 | 3 | on: 4 | push: 5 | branches: [master, gh-pages] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Sync to Gitee 12 | uses: wearerequired/git-mirror-action@master 13 | env: 14 | # 在 Settings->Secrets 配置 GITEE_RSA_PRIVATE_KEY 15 | SSH_PRIVATE_KEY: ${{ secrets.GITEE_RSA_PRIVATE_KEY }} 16 | with: 17 | # GitHub 源仓库地址 18 | source-repo: git@github.com:bijinfeng/rn-vant.git 19 | # Gitee 目标仓库地址 20 | destination-repo: git@gitee.com:bijinfeng/rn-vant.git -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - master # default branch 7 | 8 | jobs: 9 | upload-test-coverage: 10 | name: test-coverage 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: 🏗 Setup repo 14 | uses: actions/checkout@v2 15 | 16 | - name: 🏗 Setup Node 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: 16.x 20 | cache: yarn 21 | 22 | - name: 📦 Install dependencies 23 | run: yarn bootstrap 24 | 25 | - name: 📦 Test 26 | run: yarn test --maxWorkers=2 --coverage 27 | 28 | - name: 🚀 Upload coverage to codecov 29 | uses: codecov/codecov-action@v3 30 | with: 31 | # use own token to upload coverage reports 32 | token: ${{ secrets.CODECOV_TOKEN }} 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | package-lock.json 38 | lerna-debug.log 39 | 40 | # BUCK 41 | buck-out/ 42 | \.buckd/ 43 | *.keystore 44 | !debug.keystore 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/ 52 | 53 | */fastlane/report.xml 54 | */fastlane/Preview.html 55 | */fastlane/screenshots 56 | 57 | # Bundle artifact 58 | *.jsbundle 59 | 60 | # CocoaPods 61 | /ios/Pods/ 62 | 63 | # build artificial 64 | lib/ 65 | /bundle/ 66 | coverage/ 67 | 68 | # umi 69 | .umi 70 | .umi-production 71 | .env.local 72 | dist/ 73 | 74 | .yalc 75 | .yarn 76 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org/ 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@youngjuning/prettier-config'); -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": false, 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll.eslint": true // 保存时使用eslint校验文件 5 | }, 6 | "git.ignoreLimitWarning": true 7 | } 8 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | registry "https://registry.npmjs.org/" 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 bijinfeng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ./packages/rn-vant/README.md -------------------------------------------------------------------------------- /algolia/docsearch.json: -------------------------------------------------------------------------------- 1 | 2 | 3 | { 4 | "index_name": "docsearch", 5 | "start_urls": [ 6 | "https://rn-vant.vercel.app/" 7 | ], 8 | "sitemap_urls": [ 9 | "https://rn-vant.vercel.app/sitemap.xml" 10 | ], 11 | "stop_urls": [ 12 | "/search", 13 | "/v3me", 14 | "/playground", 15 | "/inspector" 16 | ], 17 | "sitemap_alternate_links": true, 18 | "selectors": { 19 | "lvl0": { 20 | "selector": ".van-doc-nav van-doc-nav__item a", 21 | "global": true, 22 | "default_value": "Documentation" 23 | }, 24 | "lvl1": "article h1", 25 | "lvl2": "article h2", 26 | "lvl3": "article h3", 27 | "lvl4": "article h4", 28 | "lvl5": "article h5, article td:first-child", 29 | "lvl6": "article h6", 30 | "text": "article p, article li, article td:last-child" 31 | }, 32 | "strip_chars": " .,;:#", 33 | "custom_settings": { 34 | "separatorsToIndex": "_", 35 | "attributesForFaceting": [ 36 | "language", 37 | "version", 38 | "type", 39 | "docusaurus_tag" 40 | ], 41 | "attributesToRetrieve": [ 42 | "hierarchy", 43 | "content", 44 | "anchor", 45 | "url", 46 | "url_without_anchor", 47 | "type" 48 | ] 49 | }, 50 | "js_render": true, 51 | "nb_hits": 856 52 | } -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /example/.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 4 | } 5 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | 13 | # macOS 14 | .DS_Store 15 | 16 | __generated__ 17 | -------------------------------------------------------------------------------- /example/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import App from './src'; 3 | 4 | export default () => ; 5 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "rn-vant-expo-demo", 4 | "description": "Rn Vant + Expo Example", 5 | "slug": "rn-vant-example", 6 | "version": "1.0.0", 7 | "orientation": "portrait", 8 | "icon": "./assets/icon.png", 9 | "splash": { 10 | "image": "./assets/splash.png", 11 | "resizeMode": "contain", 12 | "backgroundColor": "#ffffff" 13 | }, 14 | "scheme": "testing", 15 | "updates": { 16 | "fallbackToCacheTimeout": 0 17 | }, 18 | "assetBundlePatterns": [ 19 | "**/*" 20 | ], 21 | "ios": { 22 | "bundleIdentifier": "com.dice.www", 23 | "supportsTablet": true 24 | }, 25 | "android": { 26 | "adaptiveIcon": { 27 | "foregroundImage": "./assets/adaptive-icon.png", 28 | "backgroundColor": "#FFFFFF" 29 | }, 30 | "package": "com.dice.www" 31 | }, 32 | "web": { 33 | "favicon": "https://img01.yzcdn.cn/vant/logo.png" 34 | }, 35 | "packagerOpts": { 36 | "config": "metro.config.js" 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /example/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bijinfeng/rn-vant/a465ecb3f06dbdaf084b98455c6812b93f16fc43/example/assets/adaptive-icon.png -------------------------------------------------------------------------------- /example/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bijinfeng/rn-vant/a465ecb3f06dbdaf084b98455c6812b93f16fc43/example/assets/favicon.png -------------------------------------------------------------------------------- /example/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bijinfeng/rn-vant/a465ecb3f06dbdaf084b98455c6812b93f16fc43/example/assets/icon.png -------------------------------------------------------------------------------- /example/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bijinfeng/rn-vant/a465ecb3f06dbdaf084b98455c6812b93f16fc43/example/assets/splash.png -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const pak = require('../packages/rn-vant/package.json'); 3 | const iconPak = require('../packages/rn-vant-icons/package.json'); 4 | 5 | module.exports = api => { 6 | api.cache(true); 7 | return { 8 | presets: [['babel-preset-expo', { jsxRuntime: 'automatic' }]], 9 | plugins: [ 10 | [ 11 | 'module-resolver', 12 | { 13 | extensions: ['.tsx', '.ts', '.js', '.json'], 14 | alias: { 15 | // For development, we want to alias the library to the source 16 | [pak.name]: path.join(__dirname, '../packages/rn-vant/', pak.source), 17 | [iconPak.name]: path.join(__dirname, '../packages/rn-vant-icons/', iconPak.source), 18 | }, 19 | }, 20 | ], 21 | '@babel/plugin-proposal-export-namespace-from', 22 | ], 23 | }; 24 | }; 25 | -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | // /* eslint-disable import/no-commonjs */ 2 | 3 | const path = require('path'); 4 | const blacklist = require('metro-config/src/defaults/exclusionList'); 5 | const escape = require('escape-string-regexp'); 6 | const pak = require('../packages/rn-vant/package.json'); 7 | 8 | const root = path.resolve(__dirname, '..'); 9 | 10 | const modules = [ 11 | '@expo/vector-icons', 12 | 'expo-constants', 13 | 'expo-modules-core', 14 | ...Object.keys(pak.peerDependencies), 15 | ]; 16 | 17 | module.exports = { 18 | projectRoot: __dirname, 19 | watchFolders: [root], 20 | 21 | // We need to make sure that only one version is loaded for peerDependencies 22 | // So we blacklist them at the root, and alias them to the versions in example's node_modules 23 | resolver: { 24 | blacklistRE: blacklist( 25 | modules.map(m => new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)) 26 | ), 27 | 28 | extraNodeModules: modules.reduce((acc, name) => { 29 | acc[name] = path.join(__dirname, 'node_modules', name); 30 | return acc; 31 | }, {}), 32 | }, 33 | 34 | transformer: { 35 | getTransformOptions: async () => ({ 36 | transform: { 37 | experimentalImportSupport: false, 38 | inlineRequires: true, 39 | }, 40 | }), 41 | }, 42 | }; 43 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rn-vant-example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "description": "Example for RN Vant", 6 | "homepage": "/example/", 7 | "main": "node_modules/expo/AppEntry.js", 8 | "scripts": { 9 | "start": "expo start", 10 | "android": "expo start --android", 11 | "ios": "expo start --ios", 12 | "web": "expo start --web", 13 | "eject": "expo eject", 14 | "build:web": "npx expo build:web" 15 | }, 16 | "dependencies": { 17 | "@expo/webpack-config": "^0.17.0", 18 | "expo": "^46.0.0", 19 | "expo-linking": "~3.2.2", 20 | "expo-status-bar": "~1.4.0", 21 | "expo-updates": "~0.14.6", 22 | "react": "18.0.0", 23 | "react-dom": "18.0.0", 24 | "react-native": "0.69.6", 25 | "react-native-gesture-handler": "~2.5.0", 26 | "react-native-safe-area-context": "4.3.1", 27 | "react-native-screens": "~3.15.0", 28 | "react-native-web": "~0.18.7", 29 | "react-router-dom": "^6.3.0", 30 | "react-router-native": "^6.3.0" 31 | }, 32 | "devDependencies": { 33 | "@babel/core": "^7.18.6", 34 | "@babel/plugin-proposal-export-namespace-from": "^7.16.0", 35 | "@types/react": "~18.0.0", 36 | "@types/react-native": "~0.69.1", 37 | "babel-loader": "^8.2.5", 38 | "babel-plugin-module-resolver": "^4.1.0", 39 | "expo-cli": "^6.0.5", 40 | "typescript": "^4.6.3" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /example/src/GlobalContext.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ColorSchemeName } from 'react-native'; 3 | import { lightTheme } from './style/vars'; 4 | 5 | export interface GlobalState { 6 | themeMode: ColorSchemeName; 7 | isDarkMode: boolean; 8 | isInIframe: boolean; 9 | themeVars: typeof lightTheme; 10 | setThemeMode: (themeMode: ColorSchemeName) => void; 11 | } 12 | 13 | export const GlobalContext = React.createContext({} as GlobalState); 14 | -------------------------------------------------------------------------------- /example/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as DemoBlock } from './DemoBlock'; 2 | -------------------------------------------------------------------------------- /example/src/pages/calendar/CalendarSingle.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Cell, Calendar } from '@pingtou/rn-vant'; 3 | 4 | const CalendarSingle = () => { 5 | const [visible, setVisible] = useState(false); 6 | 7 | const handleConfirm = (date: Date | Date[]) => { 8 | console.log(date); 9 | setVisible(false); 10 | }; 11 | 12 | return ( 13 | <> 14 | setVisible(true)} /> 15 | setVisible(false)} /> 16 | 17 | ); 18 | }; 19 | 20 | export default CalendarSingle; 21 | -------------------------------------------------------------------------------- /example/src/pages/calendar/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import { ScrollView } from 'react-native'; 3 | import { Cell } from '@pingtou/rn-vant'; 4 | import { DemoBlock } from '../../components'; 5 | import CalendarSingle from './CalendarSingle'; 6 | 7 | const CalendarExample = memo(() => { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | }); 18 | 19 | export default CalendarExample; 20 | -------------------------------------------------------------------------------- /example/src/pages/divider/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import { ScrollView } from 'react-native'; 3 | import { Divider } from '@pingtou/rn-vant'; 4 | import { DemoBlock } from '../../components'; 5 | 6 | const DividerExample = memo(() => { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 文字 14 | 15 | 16 | 文字 17 | 文字 18 | 19 | 20 | 文字 21 | 22 | 23 | 28 | 文字 29 | 30 | 31 | 32 | ); 33 | }); 34 | 35 | export default DividerExample; 36 | -------------------------------------------------------------------------------- /example/src/pages/form/Base.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import { Form, Cell, Input, FormInstance, Button } from '@pingtou/rn-vant'; 3 | import { DemoBlock } from '../../components'; 4 | 5 | interface FormValue { 6 | username: string; 7 | password: string; 8 | } 9 | 10 | export default () => { 11 | const formRef = useRef>(null); 12 | 13 | return ( 14 | 15 | form={formRef}> 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /example/src/pages/form/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import { ScrollView, SafeAreaView } from 'react-native'; 3 | import Subscribe from './Subscribe'; 4 | import Type from './Type'; 5 | import Rules from './Rules'; 6 | import Base from './Base'; 7 | import List from './List'; 8 | 9 | const FormExample = memo(() => { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | }); 22 | 23 | export default FormExample; 24 | -------------------------------------------------------------------------------- /example/src/pages/navbar/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import Icon from '@pingtou/rn-vant-icons'; 3 | import { NavBar, Toast } from '@pingtou/rn-vant'; 4 | import { ScrollView } from 'react-native'; 5 | import { DemoBlock } from '../../components'; 6 | 7 | const NavBarDemo: FC = () => { 8 | return ( 9 | 10 | 11 | Toast.info('返回')} 17 | onPressRight={() => Toast.info('按钮')} 18 | /> 19 | 20 | 21 | Toast.info('返回')} 26 | rightText={} 27 | onPressRight={() => Toast.info('按钮')} 28 | /> 29 | 30 | 31 | ); 32 | }; 33 | 34 | export default NavBarDemo; 35 | -------------------------------------------------------------------------------- /example/src/pages/notice-bar/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import { NoticeBar } from '@pingtou/rn-vant'; 3 | import { ScrollView, View } from 'react-native'; 4 | import { DemoBlock } from '../../components'; 5 | 6 | const NoticeBarDemo: FC = () => { 7 | return ( 8 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 技术是开发它的人的共同灵魂。 23 | 24 | 技术是开发它的人的共同灵魂。 25 | 26 | 27 | 28 | 34 | 35 | 36 | ); 37 | }; 38 | 39 | export default NoticeBarDemo; 40 | -------------------------------------------------------------------------------- /example/src/pages/overlay/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useState } from 'react'; 2 | import { Button, Overlay } from '@pingtou/rn-vant'; 3 | import { View } from 'react-native'; 4 | import { DemoBlock } from '../../components'; 5 | 6 | const OverlayExample = memo(() => { 7 | const [visible, setVisible] = useState(false); 8 | const [visible1, setVisible1] = useState(false); 9 | 10 | return ( 11 | 12 | 13 | 16 | setVisible1(false)} /> 17 | 18 | 19 | 22 | setVisible(false)}> 23 | 24 | 25 | 26 | 27 | ); 28 | }); 29 | 30 | export default OverlayExample; 31 | -------------------------------------------------------------------------------- /example/src/pages/switch/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useState } from 'react'; 2 | import { ScrollView } from 'react-native'; 3 | import { Switch, Cell } from '@pingtou/rn-vant'; 4 | import { DemoBlock } from '../../components'; 5 | 6 | const SwitchExample = memo(() => { 7 | const [value] = useState(false); 8 | 9 | return ( 10 | 11 | 12 | console.log(`switch to ${checked}`)} /> 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | } center /> 31 | 32 | 33 | ); 34 | }); 35 | 36 | export default SwitchExample; 37 | -------------------------------------------------------------------------------- /example/src/utils/iframeMessage.ts: -------------------------------------------------------------------------------- 1 | import { Platform } from 'react-native'; 2 | 3 | /** 4 | * 判断是不是在 iframe 里 5 | */ 6 | export const isInIframe = Platform.OS === 'web' ? window.self !== window.top : false; 7 | 8 | /** 9 | * 监听 iframe 通信 10 | * @param _method 事件名 11 | * @param callback 回调 12 | */ 13 | export const listenerMessage = ( 14 | _method: string, 15 | callback: (data: T) => void 16 | ): { cancel: () => void } => { 17 | let cancel = () => {}; 18 | if (isInIframe) { 19 | const callbackEvent = (event: MessageEvent) => { 20 | const { method, data } = event?.data ?? {}; 21 | if (method === _method) { 22 | callback(data); 23 | } 24 | }; 25 | window.addEventListener('message', callbackEvent); 26 | cancel = () => window.removeEventListener('message', callbackEvent); 27 | } 28 | return { cancel }; 29 | }; 30 | 31 | /** 32 | * 发送 iframe 信息 33 | * @param method 事件名 34 | * @param data 信息 35 | */ 36 | export const postMessage = (method: string, data?: T): void => { 37 | if (isInIframe) { 38 | window.parent.postMessage({ method, data }, '*'); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /example/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './iframeMessage'; 2 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "paths": { 5 | "@pingtou/rn-vant": [ 6 | "../packages/rn-vant/src/index" 7 | ], 8 | "@pingtou/rn-vant-icons": [ 9 | "../packages/rn-vant-icons/src/index" 10 | ], 11 | }, 12 | "strict": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const createExpoWebpackConfigAsync = require('@expo/webpack-config'); 3 | const { resolver } = require('./metro.config'); 4 | 5 | const root = path.resolve(__dirname, '..'); 6 | // eslint-disable-next-line camelcase 7 | const node_modules = path.join(__dirname, 'node_modules'); 8 | 9 | module.exports = async (env, argv) => { 10 | const config = await createExpoWebpackConfigAsync( 11 | { 12 | ...env, 13 | babel: { 14 | dangerouslyAddModulePathsToTranspile: ['@ptomasroos/react-native-multi-slider'], 15 | }, 16 | }, 17 | argv 18 | ); 19 | 20 | config.module.rules.push({ 21 | test: /\.(js|ts|tsx)$/, 22 | include: path.resolve(root, 'packages'), 23 | use: 'babel-loader', 24 | }); 25 | 26 | // We need to make sure that only one version is loaded for peerDependencies 27 | // So we alias them to the versions in example's node_modules 28 | Object.assign(config.resolve.alias, { 29 | ...resolver.extraNodeModules, 30 | 'react-native-web': path.join(node_modules, 'react-native-web'), 31 | }); 32 | 33 | return config; 34 | }; 35 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | testRegex: '/__tests__/.*\\.(test|spec)\\.(js|tsx?)$', 4 | setupFiles: ['/jest/setup.js'], 5 | transformIgnorePatterns: [ 6 | 'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|lodash-es|@ptomasroos/react-native-multi-slider|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)', 7 | ], 8 | moduleNameMapper: { 9 | '@pingtou/rn-vant': '/packages/rn-vant/src', 10 | }, 11 | preset: 'jest-expo', 12 | }; 13 | -------------------------------------------------------------------------------- /jest/setup.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-void */ 2 | /* eslint-env jest */ 3 | /* eslint-disable import/no-extraneous-dependencies */ 4 | 5 | import 'react-native-gesture-handler/jestSetup'; 6 | 7 | jest.useFakeTimers(); 8 | // Silence the warning: Animated: `useNativeDriver` is not supported because the native animated module is missing 9 | jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper'); 10 | 11 | const { error } = console; 12 | 13 | console.error = (...args) => 14 | // Suppress error messages regarding error boundary in tests 15 | /(Consider adding an error boundary to your tree to customize error handling behavior|React will try to recreate this component tree from scratch using the error boundary you provided|Error boundaries should implement getDerivedStateFromError)/m.test( 16 | args[0] 17 | ) 18 | ? void 0 19 | : error(...args); 20 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "independent", 3 | "npmClient": "yarn", 4 | "useWorkspaces": true, 5 | "ignoreChanges": [ 6 | "ignored-file", 7 | "**/__tests__/**", 8 | "**/*.md" 9 | ], 10 | "command": { 11 | "publish": { 12 | "registry": "https://registry.npmjs.org" 13 | }, 14 | "version": { 15 | "conventionalCommits": true, 16 | "message": "chore(release): publish" 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /packages/dumi-theme-vant/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @pingtou/dumi-theme-vant 2 | 3 | ## 1.0.0 4 | 5 | ### Major Changes 6 | 7 | - [`bc96d59`](https://github.com/bijinfeng/rn-vant/commit/bc96d5955185cf0a4c62a657ec6fa5201524940d) Thanks [@bijinfeng](https://github.com/bijinfeng)! - first version 8 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/README.md: -------------------------------------------------------------------------------- 1 | ## @rn-vant/dumi-theme-vant 2 | 3 | The vant theme of dumi 4 | 5 | ``` 6 | yarn add @rn-vant/dumi-theme-vant 7 | ``` 8 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pingtou/dumi-theme-vant", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "private": true, 6 | "description": "The vant theme of vant", 7 | "files": [ 8 | "src" 9 | ], 10 | "publishConfig": { 11 | "registry": "https://registry.npmjs.org", 12 | "access": "public" 13 | }, 14 | "dependencies": { 15 | "@docsearch/react": "3.2.1", 16 | "clsx": "^1.1.1", 17 | "react-highlight": "^0.14.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/builtins/SourceCode.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Highlight from 'react-highlight'; 3 | import { useCopy } from 'dumi/theme'; 4 | import clsx from 'clsx'; 5 | import type { Language } from 'prism-react-renderer'; 6 | import './SourceCode.less'; 7 | 8 | export interface ICodeBlockProps { 9 | code: string; 10 | lang: Language; 11 | showCopy?: boolean; 12 | } 13 | 14 | export default ({ code, lang, showCopy = true }: ICodeBlockProps) => { 15 | const [copyCode, copyStatus] = useCopy(); 16 | 17 | return ( 18 |
23 | {showCopy && ( 24 | copyCode(code)} 27 | aria-hidden="true" 28 | /> 29 | )} 30 | {code} 31 |
32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/builtins/Table.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Table: React.FC = ({ children }) => {children}
; 4 | 5 | export default Table; 6 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/components/Container/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import clsx from 'clsx'; 3 | 4 | import './index.less'; 5 | 6 | export interface ContainerProps { 7 | hasSimulator?: boolean; 8 | } 9 | 10 | const Container: FC = ({ hasSimulator, children }) => ( 11 |
16 |
{children}
17 |
18 | ); 19 | 20 | export default Container; 21 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/components/SearchInput/index.less: -------------------------------------------------------------------------------- 1 | .van-doc-search { 2 | display: inline-block; 3 | vertical-align: middle; 4 | } 5 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/components/SearchInput/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import { DocSearch, DocSearchProps } from '@docsearch/react'; 3 | import '@docsearch/css'; 4 | 5 | import './index.less'; 6 | 7 | export interface SearchInputProps { 8 | searchConfig?: DocSearchProps; 9 | lang?: string; 10 | } 11 | 12 | const SearchInput: FC = props => { 13 | const { searchConfig } = props; 14 | 15 | const placeholder = searchConfig?.placeholder || 'Search...'; 16 | 17 | return ( 18 |
19 | 20 |
21 | ); 22 | }; 23 | 24 | export default SearchInput; 25 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/components/Simulator/index.less: -------------------------------------------------------------------------------- 1 | .van-doc-simulator { 2 | position: absolute; 3 | top: calc(var(--van-doc-padding) + var(--van-doc-header-top-height)); 4 | right: var(--van-doc-padding); 5 | z-index: 1; 6 | box-sizing: border-box; 7 | width: var(--van-doc-simulator-width); 8 | min-width: var(--van-doc-simulator-width); 9 | overflow: hidden; 10 | background: var(--van-doc-background-2); 11 | border-radius: var(--van-doc-border-radius); 12 | 13 | @media (max-width: 1100px) { 14 | right: auto; 15 | left: 750px; 16 | } 17 | 18 | @media (min-width: var(--van-doc-row-max-width)) { 19 | right: 50%; 20 | margin-right: calc(var(--van-doc-row-max-width) / 2 * -1 + 24px); 21 | } 22 | 23 | &-fixed { 24 | position: fixed; 25 | top: var(--van-doc-padding); 26 | } 27 | 28 | iframe { 29 | display: block; 30 | width: 100%; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useMeta'; 2 | export * from './useThemeConfig'; 3 | export * from './useHandlePostPath'; 4 | export * from './useColor'; 5 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/hooks/useColor.ts: -------------------------------------------------------------------------------- 1 | import { usePrefersColor } from 'dumi/theme'; 2 | import { useMemo } from 'react'; 3 | 4 | // 系统是否使用暗黑模式 5 | const useDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; 6 | 7 | type SetColorFunc = ReturnType[1]; 8 | 9 | export const useColor = (): ['light' | 'dark', SetColorFunc] => { 10 | const [color, setColor] = usePrefersColor(); 11 | 12 | const themeColor = useMemo<'light' | 'dark'>(() => { 13 | let lastColor = color; 14 | if (color === 'auto') { 15 | lastColor = useDark ? 'light' : 'dark'; 16 | } else { 17 | lastColor = color; 18 | } 19 | 20 | return lastColor; 21 | }, [color]); 22 | 23 | return [themeColor, setColor]; 24 | }; 25 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/hooks/useHandlePostPath.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { useHistory } from 'react-router'; 3 | 4 | import { scrollDoc } from '../utils/scrollDoc'; 5 | import { iframeMessageSwap } from '../utils'; 6 | 7 | /** 8 | * 监听 iframe 内部事件 9 | */ 10 | export const useHandleIframePost = (): void => { 11 | const history = useHistory(); 12 | 13 | useEffect(() => { 14 | const listenerEvent = iframeMessageSwap.addListener('navigate', (url?: string) => { 15 | if (url) { 16 | // 切换路由 17 | history.push(url); 18 | const scrollElement = scrollDoc(); 19 | scrollElement.scrollTop = 0; 20 | } 21 | }); 22 | return () => listenerEvent.off(); 23 | }, [history]); 24 | }; 25 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/hooks/useMeta.ts: -------------------------------------------------------------------------------- 1 | import { context } from 'dumi/theme'; 2 | import { useContext, useEffect, useState } from 'react'; 3 | 4 | import { IThemeContext } from '@umijs/preset-dumi/lib/theme/context'; 5 | 6 | export type TuyaThemeMeta = IThemeContext['meta'] & { 7 | desc?: string; 8 | demo?: string; 9 | [k: string]: any; 10 | }; 11 | 12 | export const useMeta = () => { 13 | const { meta } = useContext(context); 14 | 15 | const [metaUpdated, setMetaUpdated] = useState(meta); 16 | 17 | useEffect(() => { 18 | if (meta && Object.keys(meta).length > 0) { 19 | setMetaUpdated(meta); 20 | } 21 | }, [meta]); 22 | 23 | return metaUpdated as TuyaThemeMeta; 24 | }; 25 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/hooks/useThemeConfig.ts: -------------------------------------------------------------------------------- 1 | import { context } from 'dumi/theme'; 2 | import { useContext } from 'react'; 3 | 4 | import { IThemeContext } from '@umijs/preset-dumi/lib/theme/context'; 5 | 6 | export type VantThemeConfig = IThemeContext['config']['theme'] & { 7 | demoUrl: string; 8 | base: string; 9 | }; 10 | 11 | // 兜底默认值 12 | const defaults = {}; 13 | 14 | export const useThemeConfig = (): VantThemeConfig => { 15 | const { config } = useContext(context); 16 | const ctxConfig = config?.theme ?? {}; 17 | 18 | return Object.assign(ctxConfig, defaults) as VantThemeConfig; 19 | }; 20 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/interface.ts: -------------------------------------------------------------------------------- 1 | import type { IRouteComponentProps } from '@umijs/types'; 2 | 3 | export type Location = IRouteComponentProps['location']; 4 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/layout.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, useContext } from 'react'; 2 | import type { IRouteComponentProps } from '@umijs/types'; 3 | import { context } from 'dumi/theme'; 4 | 5 | import Header from './components/Header'; 6 | import SideMenu from './components/Nav'; 7 | import Container from './components/Container'; 8 | import Simulator from './components/Simulator'; 9 | import { Renderer } from './pages'; 10 | 11 | import { useMeta, useThemeConfig, useHandleIframePost } from './hooks'; 12 | import './style/layout.less'; 13 | 14 | const Layout: FC = ({ children, location }) => { 15 | const { meta } = useContext(context); 16 | const { title, desc, demo } = useMeta(); 17 | const { demoUrl } = useThemeConfig(); 18 | 19 | const showSideMenu = meta.sidemenu !== false; 20 | 21 | useHandleIframePost(); 22 | 23 | return ( 24 |
25 |
26 | 27 | {/* 侧边栏 */} 28 | {showSideMenu && } 29 | 30 | 31 | 32 | {children} 33 | 34 | 35 | 36 | 37 |
38 | ); 39 | }; 40 | 41 | export default Layout; 42 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/pages/index.ts: -------------------------------------------------------------------------------- 1 | export * from './rerender'; 2 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/pages/rerender/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import { useThemeConfig } from '../../hooks'; 3 | import type { Location } from '../../interface'; 4 | 5 | export interface RendererProps { 6 | location: Location; 7 | title?: string; 8 | desc?: string; 9 | } 10 | 11 | export const Renderer: FC = ({ children, location, title, desc }) => { 12 | const { base } = useThemeConfig(); 13 | const isHome = location?.pathname === base; 14 | 15 | return ( 16 |
17 | {title && !isHome &&

{title}

} 18 | {desc && ( 19 |
20 |

介绍

21 |

{desc}

22 |
23 | )} 24 | {children} 25 |
26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/style/base.less: -------------------------------------------------------------------------------- 1 | @import './var.less'; 2 | @import './font.less'; 3 | 4 | body { 5 | min-width: 1100px; 6 | margin: 0; 7 | overflow-x: auto; 8 | color: var(--van-doc-text-color-2); 9 | font-size: 16px; 10 | font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 11 | Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 12 | 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif; 13 | background-color: var(--van-doc-background); 14 | -webkit-font-smoothing: antialiased; 15 | } 16 | 17 | p { 18 | margin: 0; 19 | } 20 | 21 | h1, 22 | h2, 23 | h3, 24 | h4, 25 | h5, 26 | h6 { 27 | margin: 0; 28 | font-size: inherit; 29 | } 30 | 31 | ul, 32 | ol { 33 | margin: 0; 34 | padding: 0; 35 | list-style: none; 36 | } 37 | 38 | a { 39 | text-decoration: none; 40 | } 41 | 42 | .van-doc-row { 43 | width: 100%; 44 | 45 | @media (min-width: var(--van-doc-row-max-width)) { 46 | width: var(--van-doc-row-max-width); 47 | margin: 0 auto; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/style/layout.less: -------------------------------------------------------------------------------- 1 | @import './base.less'; 2 | @import './highlight.less'; 3 | 4 | .vant-doc-intro { 5 | padding-top: 20px; 6 | font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif; 7 | text-align: center; 8 | p { 9 | margin-bottom: 20px; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './scrollDoc'; 2 | export * from './iframeMessageSwap'; 3 | -------------------------------------------------------------------------------- /packages/dumi-theme-vant/src/utils/scrollDoc.ts: -------------------------------------------------------------------------------- 1 | const win = typeof window !== 'undefined' ? window : {}; 2 | const doc = typeof document !== 'undefined' ? document : { documentElement: {} }; 3 | // IE < 9 & Node 4 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 5 | // @ts-ignore 6 | let scrollElem = typeof win.pageYOffset === 'undefined' ? doc.documentElement : null; 7 | 8 | function detectScrollElem() { 9 | const startScrollTop = window.pageYOffset; 10 | document.documentElement.scrollTop = startScrollTop + 1; 11 | if (window.pageYOffset > startScrollTop) { 12 | document.documentElement.scrollTop = startScrollTop; 13 | // IE > 9 & FF (standard) 14 | return document.documentElement; 15 | } 16 | // Chrome (non-standard) 17 | return document.scrollingElement || document.body; 18 | } 19 | 20 | export function scrollDoc() { 21 | // eslint-disable-next-line no-return-assign 22 | return (scrollElem || (scrollElem = detectScrollElem())) as HTMLElement; 23 | } 24 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @pingtou/rn-vant-icons 2 | 3 | ## 1.0.0 4 | 5 | ### Major Changes 6 | 7 | - [`bc96d59`](https://github.com/bijinfeng/rn-vant/commit/bc96d5955185cf0a4c62a657ec6fa5201524940d) Thanks [@bijinfeng](https://github.com/bijinfeng)! - first version 8 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/README.md: -------------------------------------------------------------------------------- 1 | # Dice UI Icons 2 | 3 | ## Install 4 | 5 | #### NPM 6 | 7 | ```shell 8 | npm i @pingtou/rn-vant-icons 9 | ``` 10 | 11 | #### YARN 12 | 13 | ```shell 14 | yarn add @pingtou/rn-vant-icons 15 | ``` 16 | 17 | ## Document 18 | 19 | - [Usage in React Native](https://bijinfeng.github.io/dice/docs/components/icon) 20 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "symbol_url": "//at.alicdn.com/t/font_2952809_4bb6cudcj1k.js", 3 | "use_typescript": true, 4 | "save_dir": "./src", 5 | "default_icon_size": 18 6 | } 7 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Arrow.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Arrow: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Arrow.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Arrow = React.memo ? React.memo(Arrow) : Arrow; 30 | 31 | export default Arrow; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/ArrowDown.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let ArrowDown: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | ArrowDown.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | ArrowDown = React.memo ? React.memo(ArrowDown) : ArrowDown; 30 | 31 | export default ArrowDown; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/ArrowLeft.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let ArrowLeft: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | ArrowLeft.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | ArrowLeft = React.memo ? React.memo(ArrowLeft) : ArrowLeft; 30 | 31 | export default ArrowLeft; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/ArrowUp.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let ArrowUp: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | ArrowUp.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | ArrowUp = React.memo ? React.memo(ArrowUp) : ArrowUp; 30 | 31 | export default ArrowUp; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Circle.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Circle: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Circle.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Circle = React.memo ? React.memo(Circle) : Circle; 30 | 31 | export default Circle; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Clock.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Clock: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Clock.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Clock = React.memo ? React.memo(Clock) : Clock; 30 | 31 | export default Clock; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Fail.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Fail: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Fail.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Fail = React.memo ? React.memo(Fail) : Fail; 30 | 31 | export default Fail; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/FilterO.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let FilterO: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | FilterO.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | FilterO = React.memo ? React.memo(FilterO) : FilterO; 30 | 31 | export default FilterO; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Fire.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Fire: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Fire.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Fire = React.memo ? React.memo(Fire) : Fire; 30 | 31 | export default Fire; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Gem.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Gem: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Gem.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Gem = React.memo ? React.memo(Gem) : Gem; 30 | 31 | export default Gem; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/GuideO.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let GuideO: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | GuideO.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | GuideO = React.memo ? React.memo(GuideO) : GuideO; 30 | 31 | export default GuideO; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Info.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Info: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Info.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Info = React.memo ? React.memo(Info) : Info; 30 | 31 | export default Info; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Like.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Like: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Like.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Like = React.memo ? React.memo(Like) : Like; 30 | 31 | export default Like; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Lock.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Lock: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Lock.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Lock = React.memo ? React.memo(Lock) : Lock; 30 | 31 | export default Lock; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Minus.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Minus: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Minus.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Minus = React.memo ? React.memo(Minus) : Minus; 30 | 31 | export default Minus; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Pause.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Pause: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Pause.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Pause = React.memo ? React.memo(Pause) : Pause; 30 | 31 | export default Pause; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Play.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Play: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Play.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Play = React.memo ? React.memo(Play) : Play; 30 | 31 | export default Play; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Plus.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Plus: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Plus.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Plus = React.memo ? React.memo(Plus) : Plus; 30 | 31 | export default Plus; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Share.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Share: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Share.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Share = React.memo ? React.memo(Share) : Share; 30 | 31 | export default Share; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Stop.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Stop: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Stop.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Stop = React.memo ? React.memo(Stop) : Stop; 30 | 31 | export default Stop; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/StopCircle.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let StopCircle: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | StopCircle.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | StopCircle = React.memo ? React.memo(StopCircle) : StopCircle; 30 | 31 | export default StopCircle; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/Success.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | import React, { FunctionComponent } from 'react'; 5 | import { ViewProps } from 'react-native'; 6 | import { Svg, GProps, Path } from 'react-native-svg'; 7 | import { getIconColor } from './helper'; 8 | 9 | interface Props extends GProps, ViewProps { 10 | size?: number; 11 | color?: string | string[]; 12 | } 13 | 14 | let Success: FunctionComponent = ({ size, color, ...rest }) => { 15 | return ( 16 | 17 | 21 | 22 | ); 23 | }; 24 | 25 | Success.defaultProps = { 26 | size: 18, 27 | }; 28 | 29 | Success = React.memo ? React.memo(Success) : Success; 30 | 31 | export default Success; 32 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/src/helper.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | export const getIconColor = (color: string | string[] | undefined, index: number, defaultColor: string) => { 5 | return color 6 | ? ( 7 | typeof color === 'string' 8 | ? color 9 | : color[index] || defaultColor 10 | ) 11 | : defaultColor; 12 | }; 13 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "exclude": ["example"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/rn-vant-icons/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "paths": { 5 | "@pingtou/rn-vant-icons": ["./src/index"], 6 | }, 7 | "allowUnreachableCode": true, 8 | "importsNotUsedAsValues": "remove" 9 | }, 10 | "exclude": ["lib/**/*"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/rn-vant/.umirc.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, IConfig } from 'dumi'; 2 | 3 | const isDev = process.env.NODE_ENV === 'development'; 4 | const isProd = process.env.NODE_ENV === 'production' && process.env.PREVIEW_PR !== 'true'; 5 | 6 | export default defineConfig({ 7 | exportStatic: isProd ? {} : false, 8 | title: 'RN Vant', 9 | mode: 'site', 10 | algolia: { 11 | appId: 'TM4VZTMTDL', 12 | apiKey: 'c0a3916beb89f5500d092ab4e19143b6', 13 | indexName: 'docsearch', 14 | }, 15 | headScripts: [ 16 | { 17 | src: 'https://hm.baidu.com/hm.js?a0896c62a58a2ebf6a458b9361a6d106', 18 | async: true, 19 | }, 20 | ], 21 | favicon: 'https://img01.yzcdn.cn/vant/logo.png', 22 | logo: 'https://img01.yzcdn.cn/vant/logo.png', 23 | themeConfig: { 24 | demoUrl: isDev ? 'http://localhost:19006' : '/example', 25 | base: '/', 26 | }, 27 | navs: [ 28 | null, 29 | { 30 | logo: 'https://b.yzcdn.cn/vant/logo/github.svg', 31 | path: 'https://github.com/bijinfeng/rn-vant', 32 | }, 33 | ], 34 | resolve: { 35 | passivePreview: true, 36 | }, 37 | hash: isProd, 38 | base: '/', 39 | publicPath: '/', 40 | sitemap: { 41 | hostname: 'https://bijinfeng.github.io/rn-vant/', 42 | }, 43 | // more config: https://d.umijs.org/config 44 | } as IConfig); 45 | -------------------------------------------------------------------------------- /packages/rn-vant/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @pingtou/rn-vant 2 | 3 | ## 1.0.0 4 | 5 | ### Major Changes 6 | 7 | - [`bc96d59`](https://github.com/bijinfeng/rn-vant/commit/bc96d5955185cf0a4c62a657ec6fa5201524940d) Thanks [@bijinfeng](https://github.com/bijinfeng)! - first version 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [[`bc96d59`](https://github.com/bijinfeng/rn-vant/commit/bc96d5955185cf0a4c62a657ec6fa5201524940d)]: 12 | - @pingtou/rn-vant-icons@1.0.0 13 | -------------------------------------------------------------------------------- /packages/rn-vant/docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | --- 2 | nav: 3 | path: / 4 | 5 | group: 6 | title: 开发指南 7 | 8 | demo: / 9 | 10 | title: 更新日志 11 | order: 3 12 | --- 13 | -------------------------------------------------------------------------------- /packages/rn-vant/docs/get-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | demo: / 3 | 4 | nav: 5 | path: / 6 | 7 | group: 8 | title: 开发指南 9 | 10 | title: 快速上手 11 | order: 2 12 | --- 13 | 14 | ## 安装 15 | 16 | ```sh 17 | $ yarn add rn-vant 18 | ``` 19 | -------------------------------------------------------------------------------- /packages/rn-vant/docs/home.md: -------------------------------------------------------------------------------- 1 | --- 2 | demo: / 3 | 4 | nav: 5 | path: / 6 | 7 | group: 8 | title: 开发指南 9 | order: 1 10 | 11 | title: 介绍 12 | order: 1 13 | --- 14 | -------------------------------------------------------------------------------- /packages/rn-vant/docs/icon.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Icon 图标 3 | desc: 基于 svg 的图标集,可以通过 Icon 组件使用,也可以在其他组件中通过 icon 属性引用。 4 | demo: /icon 5 | nav: 6 | path: / 7 | 8 | group: 9 | title: 基础组件 10 | --- 11 | 12 | ## 代码演示 13 | 14 | ### 基础用法 15 | 16 | 通过 `name` 属性来指定需要使用的图标,Vant 内置了一套图标库(见右侧示例),可以直接传入对应的名称来使用。 17 | 18 | ```html 19 | 20 | ``` 21 | 22 | ### 图标颜色 23 | 24 | 通过 `color` 属性来设置图标的颜色。 25 | 26 | ```html 27 | 28 | ``` 29 | 30 | ### 图标大小 31 | 32 | 通过 `size` 属性来设置图标的尺寸大小。 33 | 34 | ```html 35 | 36 | ``` 37 | 38 | ## API 39 | 40 | ### Props 41 | 42 | | 参数 | 说明 | 类型 | 默认值 | 43 | | ----- | -------- | -------- | ------ | 44 | | name | 图标名称 | _string_ | | 45 | | size | 图标大小 | _number_ | | 46 | | color | 图标颜色 | _string_ | | 47 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ActionBar/ActionBar.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from 'react'; 2 | import View from '../View'; 3 | import type { ActionBarProps } from './type'; 4 | import ActionBarContext from './ActionBarContext'; 5 | import { useThemeFactory } from '../Theme'; 6 | import { createBarStyles } from './style'; 7 | 8 | const ActionBar: React.FC = props => { 9 | const { safeAreaInsetBottom = true } = props; 10 | const { styles } = useThemeFactory(createBarStyles); 11 | const children = useMemo(() => React.Children.toArray(props.children), [props.children]); 12 | 13 | return ( 14 | 15 | 16 | {React.Children.toArray(props.children) 17 | .filter(React.isValidElement) 18 | .map((child: React.ReactElement, index) => 19 | React.cloneElement(child, { 20 | index, 21 | }) 22 | )} 23 | 24 | 25 | ); 26 | }; 27 | 28 | export default ActionBar; 29 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ActionBar/ActionBarContext.ts: -------------------------------------------------------------------------------- 1 | import { createContext, Context } from 'react'; 2 | 3 | export interface ActionBarState { 4 | parent?: Record; 5 | } 6 | 7 | const ActionButtonContext: Context = createContext({}); 8 | 9 | export default ActionButtonContext; 10 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ActionBar/ActionBarIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Text, View } from 'react-native'; 3 | import Badge from '../Badge'; 4 | import TouchableOpacity from '../TouchableOpacity'; 5 | import { useThemeFactory } from '../Theme'; 6 | import type { ActionBarIconProps } from './type'; 7 | import { createIconStyle } from './style'; 8 | 9 | const ActionBarIcon: React.FC = props => { 10 | const { styles, theme } = useThemeFactory(createIconStyle); 11 | const { badge, icon } = props; 12 | 13 | const renderIcon = () => { 14 | return badge ? {icon} : icon; 15 | }; 16 | 17 | return ( 18 | 24 | {renderIcon()} 25 | {props.children || props.text} 26 | 27 | ); 28 | }; 29 | 30 | export default ActionBarIcon; 31 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ActionBar/index.tsx: -------------------------------------------------------------------------------- 1 | import ActionBar from './ActionBar'; 2 | import ActionBarIcon from './ActionBarIcon'; 3 | import ActionBarButton from './ActionBarButton'; 4 | 5 | const ActionBarNamespace = Object.assign(ActionBar, { 6 | Icon: ActionBarIcon, 7 | Button: ActionBarButton, 8 | }); 9 | 10 | export default ActionBarNamespace; 11 | export { ActionBarNamespace as ActionBar }; 12 | export type { ActionBarProps, ActionBarIconProps, ActionBarButtonProps } from './type'; 13 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ActionBar/type.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { StyleProp, TextStyle, ViewStyle } from 'react-native'; 3 | import type { BadgeProps } from '../Badge/type'; 4 | import type { ButtonType } from '../Button/type'; 5 | 6 | export interface ActionBarProps { 7 | /** 是否开启底部安全区适配 */ 8 | safeAreaInsetBottom?: boolean; 9 | style?: StyleProp; 10 | } 11 | 12 | export interface ActionBarIconProps { 13 | /** 按钮文字 */ 14 | text?: React.ReactNode; 15 | /** 图标 */ 16 | icon?: React.ReactNode; 17 | /** 图标右上角徽标的内容 */ 18 | badge?: BadgeProps; 19 | style?: StyleProp; 20 | onPress?: () => void; 21 | } 22 | 23 | export interface ActionBarButtonProps { 24 | /** 按钮文字 */ 25 | text?: React.ReactNode; 26 | /** 按钮类型 */ 27 | type?: ButtonType; 28 | /** 按钮图标 */ 29 | icon?: string | React.ReactNode; 30 | /** 按钮颜色,支持传入 linear-gradient 渐变色 */ 31 | color?: string; 32 | /** 是否禁用按钮 */ 33 | disabled?: boolean; 34 | /** 是否显示为加载状态 */ 35 | loading?: boolean; 36 | onPress?: () => void; 37 | /** @private */ 38 | index?: number; 39 | style?: StyleProp; 40 | textStyle?: StyleProp; 41 | } 42 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ActionSheet/index.ts: -------------------------------------------------------------------------------- 1 | import ActionSheet from './ActionSheet'; 2 | 3 | export { ActionSheet }; 4 | export default ActionSheet; 5 | export type { ActionSheetAction, ActionSheetProps } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ActionSheet/type.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { StyleProp, ViewStyle } from 'react-native'; 3 | import type { PopupProps } from '../Popup/type'; 4 | 5 | export interface TextNodeProps { 6 | children: string | React.ReactElement; 7 | style?: StyleProp; 8 | } 9 | 10 | export interface ActionSheetAction { 11 | // 标题 12 | name: string; 13 | // 二级标题 14 | subname?: string; 15 | // 选项文字颜色 16 | color?: string; 17 | // 为对应列添加额外的 style 18 | style?: StyleProp; 19 | // 是否为加载状态 20 | loading?: boolean; 21 | // 是否为禁用状态 22 | disabled?: boolean; 23 | // 点击时触发的回调函数 24 | callback?: (action: ActionSheetAction) => void; 25 | } 26 | 27 | export interface ActionSheetProps extends PopupProps { 28 | // 面板选项列表 29 | actions?: ActionSheetAction[]; 30 | // 顶部标题 31 | title?: string | React.ReactElement; 32 | // 取消按钮文字 33 | cancelText?: string | React.ReactElement; 34 | // 选项上方的描述信息 35 | description?: string | React.ReactElement; 36 | // 点击选项时触发,禁用或加载状态下不会触发 37 | onSelect?: (action: ActionSheetAction, index: number) => void; 38 | // 点击取消按钮时触发 39 | onCancel?: () => void; 40 | } 41 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Badge/index.ts: -------------------------------------------------------------------------------- 1 | import Badge from './Badge'; 2 | 3 | export default Badge; 4 | export { Badge }; 5 | export type { BadgeProps } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Badge/type.ts: -------------------------------------------------------------------------------- 1 | import type { ViewProps } from 'react-native'; 2 | import type React from 'react'; 3 | 4 | export interface BadgeProps extends ViewProps { 5 | /** 徽标内容 */ 6 | content?: React.ReactNode; 7 | /** 是否展示为小红点 */ 8 | dot?: boolean; 9 | /** 最大值,超过最大值会显示 {max}+,仅当 content 为数字时有效 */ 10 | max?: number | string; 11 | /** 徽标背景颜色 */ 12 | color?: string; 13 | /** 设置徽标的偏移量,数组的两项分别对应水平和垂直方向的偏移量 */ 14 | offset?: Array; 15 | /** 16 | * 当 content 为数字 0 时,是否展示徽标 17 | * @default true 18 | */ 19 | showZero?: boolean; 20 | } 21 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Button/index.ts: -------------------------------------------------------------------------------- 1 | import Button from './Button'; 2 | 3 | export default Button; 4 | export { Button }; 5 | export type { ButtonProps, ButtonSize, ButtonType } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Calendar/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Calendar 日历 3 | desc: 日历组件用于选择日期或日期区间。 4 | demo: /calendar 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 表单组件 11 | --- 12 | 13 | ## 引入 14 | 15 | ```js 16 | import { Calendar } from '@pingtou/rn-vant'; 17 | ``` 18 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Calendar/index.ts: -------------------------------------------------------------------------------- 1 | import Calendar from './Calendar'; 2 | 3 | export default Calendar; 4 | export { Calendar }; 5 | export type { 6 | CalendarProps, 7 | CalendarType, 8 | CalendarDayItem, 9 | CalendarDayType, 10 | CalendarInstance, 11 | } from './type'; 12 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Cell/CellGroup.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from 'react'; 2 | import { View, Text } from 'react-native'; 3 | import { useThemeFactory } from '../Theme'; 4 | import { createCellGroupStyle } from './style'; 5 | import type { CellGroupProps } from './type'; 6 | 7 | const CellGroup = forwardRef((props, ref) => { 8 | const { children, title, border = true, inset, ...rest } = props; 9 | const { styles } = useThemeFactory(createCellGroupStyle); 10 | const hasBorder = border && !inset; 11 | 12 | return ( 13 | 14 | {title && {title}} 15 | 22 | {React.Children.map(children, (child, i) => ( 23 | <> 24 | {i !== 0 && } 25 | {child} 26 | 27 | ))} 28 | 29 | 30 | ); 31 | }); 32 | 33 | CellGroup.displayName = 'Cell.Group'; 34 | 35 | export default CellGroup; 36 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Cell/index.ts: -------------------------------------------------------------------------------- 1 | import CellComponent from './Cell'; 2 | import CellGroup from './CellGroup'; 3 | 4 | export const Cell = Object.assign(CellComponent, { Group: CellGroup }); 5 | 6 | export default Cell; 7 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Checkbox/content.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { StyleProp, ViewStyle } from 'react-native'; 3 | 4 | export type CheckboxValueType = string | number | boolean; 5 | 6 | export interface CheckboxOptionType { 7 | label: React.ReactNode; 8 | value: CheckboxValueType; 9 | style?: StyleProp; 10 | disabled?: boolean; 11 | onChange?: () => void; 12 | } 13 | 14 | export interface CheckboxGroupContext { 15 | toggleOption?: (option: CheckboxOptionType) => void; 16 | value?: any; 17 | disabled?: boolean; 18 | registerValue: (val: string) => void; 19 | cancelValue: (val: string) => void; 20 | } 21 | 22 | export const GroupContext = React.createContext(null); 23 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Checkbox/index.style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | const createStyle = (theme: DiceUI.Theme) => { 4 | return StyleSheet.create({ 5 | checkbox: { 6 | alignItems: 'center', 7 | flexDirection: 'row', 8 | }, 9 | icon: { 10 | alignItems: 'center', 11 | borderColor: theme.checkbox_icon_border_color, 12 | borderWidth: 1, 13 | justifyContent: 'center', 14 | }, 15 | iconChecked: { 16 | backgroundColor: theme.checkbox_checked_icon_color, 17 | borderColor: theme.checkbox_checked_icon_color, 18 | }, 19 | iconDisabled: { 20 | backgroundColor: theme.checkbox_disabled_background_color, 21 | borderColor: theme.checkbox_disabled_icon_color, 22 | }, 23 | label: { 24 | color: theme.checkbox_label_color, 25 | }, 26 | labelContainer: { 27 | marginLeft: theme.checkbox_label_margin, 28 | }, 29 | labelDisabled: { 30 | color: theme.checkbox_disabled_label_color, 31 | }, 32 | }); 33 | }; 34 | 35 | export default createStyle; 36 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Checkbox/index.ts: -------------------------------------------------------------------------------- 1 | import InternalCheckbox from './Checkbox'; 2 | import Group from './Group'; 3 | 4 | export type { CheckboxProps } from './Checkbox'; 5 | export type { CheckboxGroupProps } from './Group'; 6 | export type { CheckboxOptionType } from './content'; 7 | 8 | type CheckboxType = typeof InternalCheckbox; 9 | 10 | interface CheckboxProps extends CheckboxType { 11 | Group: typeof Group; 12 | __ANT_CHECKBOX: boolean; 13 | } 14 | 15 | export const Checkbox = InternalCheckbox as CheckboxProps; 16 | 17 | Checkbox.Group = Group; 18 | Checkbox.__ANT_CHECKBOX = true; 19 | 20 | export default Checkbox; 21 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Circle/index.ts: -------------------------------------------------------------------------------- 1 | import Circle from './Circle'; 2 | 3 | export default Circle; 4 | export { Circle }; 5 | export type { CircleProps, CircleStartPosition } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Circle/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import type { ViewStyle, TextStyle } from 'react-native'; 3 | import type { CircleProps } from './type'; 4 | 5 | interface Styles { 6 | wrapper: ViewStyle; 7 | svg: ViewStyle; 8 | text: TextStyle; 9 | textContainer: ViewStyle; 10 | } 11 | 12 | type ExtraParams = Pick; 13 | 14 | export const createStyle = (theme: DiceUI.Theme, params: ExtraParams): Styles => { 15 | const { size } = params; 16 | const circleSize = size ?? theme.circle_size; 17 | 18 | return StyleSheet.create({ 19 | svg: { 20 | height: '100%', 21 | left: 0, 22 | position: 'absolute', 23 | top: 0, 24 | width: '100%', 25 | }, 26 | text: { 27 | color: theme.circle_text_color, 28 | fontSize: theme.circle_text_font_size, 29 | fontWeight: theme.circle_text_font_weight, 30 | lineHeight: theme.circle_text_line_height, 31 | }, 32 | textContainer: { 33 | alignItems: 'center', 34 | height: '100%', 35 | justifyContent: 'center', 36 | padding: theme.padding_base, 37 | position: 'absolute', 38 | width: '100%', 39 | }, 40 | wrapper: { 41 | height: circleSize, 42 | position: 'relative', 43 | width: circleSize, 44 | }, 45 | }); 46 | }; 47 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Circle/type.ts: -------------------------------------------------------------------------------- 1 | import type { ViewProps } from 'react-native'; 2 | import type { PathProps } from 'react-native-svg'; 3 | 4 | export type CircleStartPosition = 'top' | 'right' | 'bottom' | 'left'; 5 | 6 | export interface CircleProps extends ViewProps { 7 | /** 当前进度 */ 8 | rate?: number; 9 | /** 圆环直径 */ 10 | size?: number; 11 | /** 进度条颜色,传入对象格式可以定义渐变色 */ 12 | color?: string | Record; 13 | /** 轨道颜色 */ 14 | layerColor?: string; 15 | /** 填充颜色 */ 16 | fill?: string; 17 | /** 动画速度(单位为 rate/s) */ 18 | speed?: number; 19 | /** 进度条宽度 */ 20 | strokeWidth?: number; 21 | /** 进度条端点的形状,可选值为 square butt */ 22 | strokeLinecap?: PathProps['strokeLinecap']; 23 | /** 是否顺时针增加 */ 24 | clockwise?: boolean; 25 | /** 进度起始位置 */ 26 | startPosition?: CircleStartPosition; 27 | text?: string; 28 | } 29 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Collapse/CollapseItem.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from 'react'; 2 | import { View, Text, Animated } from 'react-native'; 3 | import { useThemeFactory } from '../Theme'; 4 | import Cell from '../Cell'; 5 | import type { CollapseItemProps } from './type'; 6 | import { createStyle } from './style'; 7 | 8 | const CollapseItem = forwardRef((props, ref) => { 9 | const { 10 | children, 11 | disabled, 12 | readonly, 13 | style, 14 | expanded = false, 15 | isLink = true, 16 | onExpand, 17 | ...rest 18 | } = props; 19 | const { styles } = useThemeFactory(createStyle); 20 | 21 | const onPressTitle = () => { 22 | if (!disabled && !readonly) { 23 | onExpand?.(!expanded); 24 | } 25 | }; 26 | 27 | return ( 28 | 29 | 37 | {expanded && ( 38 | 39 | {children} 40 | 41 | )} 42 | 43 | ); 44 | }); 45 | 46 | export default CollapseItem; 47 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Collapse/index.ts: -------------------------------------------------------------------------------- 1 | import _Collapse from './Collapse'; 2 | import CollapseItem from './CollapseItem'; 3 | 4 | const Collapse = Object.assign(_Collapse, { Item: CollapseItem }); 5 | export default Collapse; 6 | export { Collapse, CollapseItem }; 7 | export type { CollapseProps, CollapseItemProps } from './type'; 8 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Collapse/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import type { ViewStyle, TextStyle } from 'react-native'; 3 | 4 | interface Styles { 5 | contentWrapper: ViewStyle; 6 | content: TextStyle; 7 | } 8 | 9 | export const createStyle = (theme: DiceUI.Theme): Styles => { 10 | return StyleSheet.create({ 11 | content: { 12 | color: theme.collapse_item_content_text_color, 13 | fontSize: theme.collapse_item_content_font_size, 14 | lineHeight: theme.collapse_item_content_line_height, 15 | }, 16 | contentWrapper: { 17 | backgroundColor: theme.collapse_item_content_background_color, 18 | borderTopColor: theme.border_color, 19 | borderTopWidth: 1, 20 | marginHorizontal: theme.collapse_item_content_padding_horizontal, 21 | paddingVertical: theme.collapse_item_content_padding_vertical, 22 | }, 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Collapse/type.ts: -------------------------------------------------------------------------------- 1 | import type { StyleProp, ViewStyle } from 'react-native'; 2 | import type { CellProps } from '../Cell/type'; 3 | 4 | export interface CollapseProps { 5 | children?: React.ReactNode; 6 | style?: StyleProp; 7 | /** 是否开启手风琴模式 */ 8 | accordion?: boolean; 9 | /** 默认打开的面板name */ 10 | initExpanded?: string | number | Array; 11 | /** 是否显示外边框 */ 12 | border?: boolean; 13 | /** 当前展开面板的 name */ 14 | value?: number | string | Array; 15 | /** 切换面板时触发 */ 16 | onChange?: (activeNames: number | string | Array) => void; 17 | } 18 | 19 | export interface CollapseItemProps extends CellProps { 20 | /** 唯一标识符,默认为索引值 */ 21 | name?: number | string; 22 | /** 是否禁用面板 */ 23 | disabled?: boolean; 24 | /** 是否为只读状态,只读状态下无法操作面板 */ 25 | readonly?: boolean; 26 | expanded?: boolean; 27 | onExpand?: (expand: boolean) => void; 28 | children: React.ReactNode; 29 | } 30 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ConfigProvider/ConfigProviderContext.ts: -------------------------------------------------------------------------------- 1 | import { createContext, Context } from 'react'; 2 | import { zhCN as locale } from '../locale'; 3 | import type { Locale } from '../locale/lang/base'; 4 | 5 | export type ConfigProviderContextState = { 6 | locale: Locale; 7 | }; 8 | 9 | export const INITIAL_STATE = { 10 | locale, 11 | } as ConfigProviderContextState; 12 | 13 | const ConfigProvider: Context = createContext(INITIAL_STATE); 14 | 15 | export default ConfigProvider; 16 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ConfigProvider/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ConfigProvider 全局配置 3 | desc: 用于全局配置组件,提供深色模式、主题定制等能力。 4 | demo: /config-provider 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 基础组件 11 | --- 12 | 13 | ## 引入 14 | 15 | ConfigProvider 使用 React 的 context 特性,只需在应用外围包裹一次即可全局生效。 16 | 17 | ```jsx 18 | import { ConfigProvider } from 'react-vant'; 19 | 20 | export default () => ( 21 | 22 | 23 | 24 | ); 25 | ``` 26 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ConfigProvider/index.tsx: -------------------------------------------------------------------------------- 1 | import ConfigProvider from './ConfigProvider'; 2 | 3 | export { ConfigProvider }; 4 | export type { ConfigProviderProps } from './type'; 5 | export { PortalRef } from './ConfigProvider'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ConfigProvider/type.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { Locale } from '../locale/lang/base'; 3 | 4 | export interface ConfigProviderProps { 5 | locale?: Locale; 6 | children: React.ReactNode; 7 | theme?: DiceUI.Theme; 8 | } 9 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Dash/Dash.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 自定义虚线组件 3 | * 代码来自:https://github.com/obipawan/react-native-dash 4 | */ 5 | import React, { FC } from 'react'; 6 | import { View, StyleSheet } from 'react-native'; 7 | import type { DashProps } from './interface'; 8 | import { getDashStyle, isStyleRow } from './util'; 9 | import measureMeHOC, { MeasureMeState } from './measureMeHOC'; 10 | 11 | const Dash: FC = props => { 12 | const { dashGap = 2, dashLength = 4, dashThickness = 1, dashColor = 'black', style } = props; 13 | 14 | const isRow = isStyleRow(props.style); 15 | const length = isRow ? props.width : props.height; 16 | const n = Math.ceil(length / (dashGap + dashLength)); 17 | const calculatedDashStyles = getDashStyle({ 18 | dashGap, 19 | dashLength, 20 | dashThickness, 21 | dashColor, 22 | style, 23 | }); 24 | 25 | const dash = []; 26 | for (let i = 0; i < n; i++) { 27 | dash.push(); 28 | } 29 | 30 | return ( 31 | 32 | {dash} 33 | 34 | ); 35 | }; 36 | 37 | const styles = StyleSheet.create({ 38 | column: { flexDirection: 'column' }, 39 | row: { flexDirection: 'row' }, 40 | }); 41 | 42 | export default measureMeHOC(Dash); 43 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Dash/index.ts: -------------------------------------------------------------------------------- 1 | import Dash from './Dash'; 2 | 3 | export default Dash; 4 | export { Dash }; 5 | export type { DashProps } from './interface'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Dash/interface.ts: -------------------------------------------------------------------------------- 1 | import type { ViewStyle, StyleProp, ViewProps, ColorValue } from 'react-native'; 2 | 3 | export interface DashProps extends ViewProps { 4 | /** 5 | * 两个破折号之间的间隔 6 | * @default 2 7 | */ 8 | dashGap?: number; 9 | /** 10 | * 破折号的长度 11 | * @default 4 12 | */ 13 | dashLength?: number; 14 | /** 15 | * 破折号的高度 16 | * @default 1 17 | */ 18 | dashThickness?: number; 19 | /** 20 | * 容器的样式 21 | */ 22 | style?: StyleProp; 23 | /** 24 | * 破折号的颜色 25 | */ 26 | dashColor?: string | ColorValue; 27 | /** 28 | * 破折号的样式 29 | */ 30 | dashStyle?: StyleProp; 31 | } 32 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Dash/measureMeHOC.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 获取 React-Native components 的 `width` 和 `height` 3 | * 代码来自:https://github.com/obipawan/react-native-measureme 4 | */ 5 | import React, { useState } from 'react'; 6 | import { View } from 'react-native'; 7 | import type { ViewProps } from 'react-native'; 8 | 9 | export type MeasureMeState = { 10 | width: number; 11 | height: number; 12 | initialRender: true; 13 | }; 14 | 15 | const measureMeHOC = 16 |

(ComposedComponent: React.ComponentType

): React.FC

=> 17 | props => { 18 | const [state, setState] = useState(); 19 | 20 | const handleLayout: ViewProps['onLayout'] = ({ 21 | nativeEvent: { layout: { width = 0, height = 0 } = {} } = {}, 22 | }) => { 23 | setState({ width, height, initialRender: true }); 24 | }; 25 | 26 | return state?.initialRender ? ( 27 | 28 | ) : ( 29 | 30 | ); 31 | }; 32 | 33 | export default measureMeHOC; 34 | -------------------------------------------------------------------------------- /packages/rn-vant/src/DatetimePicker/DatetimePicker.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from 'react'; 2 | import type { View } from 'react-native'; 3 | import DatePicker from './DatePicker'; 4 | import TimePicker from './TimePicker'; 5 | import type { DateTimePickerProps, TimePickerProps, DatePickerProps } from './type'; 6 | 7 | const DatetimePicker = forwardRef((props, ref) => { 8 | const isTimePicker = props.type === 'time'; 9 | 10 | if (isTimePicker) { 11 | return ; 12 | } 13 | 14 | return ; 15 | }); 16 | 17 | export default DatetimePicker; 18 | -------------------------------------------------------------------------------- /packages/rn-vant/src/DatetimePicker/index.ts: -------------------------------------------------------------------------------- 1 | import DatetimePicker from './DatetimePicker'; 2 | 3 | export default DatetimePicker; 4 | export { DatetimePicker }; 5 | export type { DateTimePickerProps, DatetimePickerType } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/DatetimePicker/utils.ts: -------------------------------------------------------------------------------- 1 | export function times(n: number, iteratee: (index: number) => string): unknown[] { 2 | let index = -1; 3 | const result = Array(n); 4 | 5 | while (++index < n) { 6 | result[index] = iteratee(index); 7 | } 8 | 9 | return result; 10 | } 11 | 12 | export function getMonthEndDay(year: number, month: number): number { 13 | return 32 - new Date(year, month - 1, 32).getDate(); 14 | } 15 | 16 | export function padZero(num: number | string, targetLength = 2): string { 17 | let str = `${num}`; 18 | 19 | while (str.length < targetLength) { 20 | str = `0${str}`; 21 | } 22 | 23 | return str; 24 | } 25 | 26 | export const splitDate = (_date: Date): [number, number, number, number, number] => { 27 | const year = _date.getFullYear(); 28 | const month = _date.getMonth() + 1; 29 | const date = _date.getDate(); 30 | const hour = _date.getHours(); 31 | const minute = _date.getMinutes(); 32 | 33 | return [year, month, date, hour, minute]; 34 | }; 35 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Divider/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Divider 分割线 3 | desc: 用于将内容分隔为多个区域。 4 | demo: /divider 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 展示组件 11 | --- 12 | 13 | ### 基础用法 14 | 15 | 默认渲染一条水平分割线。 16 | 17 | ```jsx 18 | 19 | ``` 20 | 21 | ### 展示文字 22 | 23 | 通过插槽在可以分割线中间插入内容。 24 | 25 | ```jsx 26 | 文字 27 | ``` 28 | 29 | ### 内容位置 30 | 31 | 通过 `contentPosition` 指定内容所在位置。 32 | 33 | ```jsx 34 | 文字 35 | 文字 36 | ``` 37 | 38 | ### 虚线 39 | 40 | 添加 `dashed` 属性使分割线渲染为虚线。 41 | 42 | ```jsx 43 | 文字 44 | ``` 45 | 46 | ### 自定义样式 47 | 48 | 可以直接通过 `style` 属性设置分割线的样式。 49 | 50 | ```jsx 51 | 56 | 文字 57 | 58 | ``` 59 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Divider/index.ts: -------------------------------------------------------------------------------- 1 | import Divider from './Divider'; 2 | 3 | export default Divider; 4 | export { Divider }; 5 | export type { DividerProps } from './interface'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Divider/interface.ts: -------------------------------------------------------------------------------- 1 | import type { ViewStyle, TextStyle, StyleProp } from 'react-native'; 2 | 3 | export interface DividerProps { 4 | /** 5 | * 外层容器自定义样式 6 | */ 7 | style?: StyleProp; 8 | 9 | /** 10 | * 自定义文字样式 11 | */ 12 | textStyle?: StyleProp; 13 | 14 | /** 15 | * 自定义线样式 16 | */ 17 | lineStyle?: StyleProp; 18 | 19 | /** 20 | * 是否使用虚线 21 | * 22 | * @default false 23 | */ 24 | dashed?: boolean; 25 | 26 | /** 27 | * 是否使用 0.5px 线 28 | * 29 | * @default true 30 | */ 31 | hairline?: boolean; 32 | 33 | /** 34 | * 内容位置,可选值为 `'left' | 'center' | 'right'` 35 | * 36 | * @default 'center' 37 | */ 38 | contentPosition?: 'left' | 'center' | 'right'; 39 | children?: string; 40 | } 41 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Divider/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import type { DividerProps } from './interface'; 3 | 4 | type Params = Pick; 5 | 6 | export const createStyle = (theme: DiceUI.Theme, { dashed, hairline, contentPosition }: Params) => { 7 | return StyleSheet.create({ 8 | divider: { 9 | alignItems: 'center', 10 | flexDirection: 'row', 11 | marginVertical: theme.divider_margin_vertical, 12 | }, 13 | 14 | line: { 15 | borderBottomWidth: hairline ? StyleSheet.hairlineWidth : 1, 16 | borderColor: theme.divider_border_color, 17 | borderStyle: dashed ? 'dashed' : 'solid', 18 | flex: 1, 19 | height: 0, 20 | }, 21 | 22 | lineLeft: { 23 | marginRight: theme.divider_margin_horizontal, 24 | maxWidth: contentPosition === 'left' ? theme.divider_content_left_width : 'auto', 25 | }, 26 | 27 | lineRight: { 28 | marginLeft: theme.divider_margin_horizontal, 29 | maxWidth: contentPosition === 'right' ? theme.divider_content_right_width : 'auto', 30 | }, 31 | 32 | text: { 33 | color: theme.divider_text_color, 34 | fontSize: theme.divider_font_size, 35 | lineHeight: theme.divider_line_height, 36 | }, 37 | }); 38 | }; 39 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Empty/index.ts: -------------------------------------------------------------------------------- 1 | import Empty from './Empty'; 2 | 3 | export default Empty; 4 | export { Empty }; 5 | export type { EmptyProps } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Empty/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import type { ViewStyle, TextStyle } from 'react-native'; 3 | 4 | type Styles = { 5 | empty: ViewStyle; 6 | description: TextStyle; 7 | bottom: ViewStyle; 8 | }; 9 | 10 | export const createStyle = (theme: DiceUI.Theme): Styles => { 11 | return StyleSheet.create({ 12 | bottom: { 13 | marginTop: theme.empty_bottom_margin_top, 14 | }, 15 | description: { 16 | color: theme.empty_description_color, 17 | fontSize: theme.empty_description_font_size, 18 | lineHeight: theme.empty_description_line_height, 19 | marginTop: theme.empty_description_margin_top, 20 | paddingHorizontal: theme.empty_description_padding_horizontal, 21 | paddingVertical: theme.empty_description_padding_vertical, 22 | }, 23 | empty: { 24 | alignItems: 'center', 25 | justifyContent: 'center', 26 | paddingHorizontal: theme.empty_padding_horizontal, 27 | paddingVertical: theme.empty_padding_vertical, 28 | }, 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Empty/type.ts: -------------------------------------------------------------------------------- 1 | import type { ViewProps } from 'react-native'; 2 | 3 | export interface EmptyProps extends ViewProps { 4 | /** 图片类型,可选值为 error network search,支持传入图片 URL */ 5 | image?: 'default' | 'error' | 'network' | 'search' | string | React.ReactNode; 6 | imageSize?: number; 7 | /** 图片下方的描述文字 */ 8 | description?: React.ReactNode; 9 | } 10 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Field/index.ts: -------------------------------------------------------------------------------- 1 | import Field from './Field'; 2 | 3 | export default Field; 4 | export { Field }; 5 | export type { FieldProps, FieldInstance, FieldType } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Form/Form.tsx: -------------------------------------------------------------------------------- 1 | import React, { useImperativeHandle } from 'react'; 2 | import { View } from 'react-native'; 3 | import { useForm, FieldValues, FormProvider } from 'react-hook-form'; 4 | import { FormContext } from './FormContext'; 5 | import type { FormProps } from './type'; 6 | 7 | const Form = (props: FormProps) => { 8 | const { 9 | children, 10 | showValidateMessage = true, 11 | layout, 12 | colon, 13 | style, 14 | form, 15 | mode = 'onChange', 16 | ...formProps 17 | } = props; 18 | const methods = useForm({ mode, ...formProps }); 19 | 20 | useImperativeHandle(form, () => methods); 21 | 22 | return ( 23 | {...methods}> 24 | 25 | {children} 26 | 27 | 28 | ); 29 | }; 30 | 31 | export default Form; 32 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Form/FormContext.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { FormLayout } from './type'; 3 | 4 | export interface FormContextType { 5 | layout?: FormLayout; 6 | colon?: boolean; 7 | showValidateMessage?: boolean; 8 | } 9 | 10 | export const FormContext = React.createContext({} as FormContextType); 11 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Form/FormItem.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import isUndefined from 'lodash-es/isUndefined'; 3 | import { useController, useFormContext } from 'react-hook-form'; 4 | import Field from '../Field'; 5 | import type { FormItemProps } from './type'; 6 | 7 | const FormItem = (props: FormItemProps) => { 8 | const { name, children, defaultValue, rules, shouldUnregister, required, ...fieldProps } = props; 9 | const { control } = useFormContext(); 10 | const { field, fieldState } = useController({ 11 | control, 12 | name, 13 | defaultValue, 14 | rules, 15 | shouldUnregister, 16 | }); 17 | 18 | const isRequired = !isUndefined(required) ? required : rules && !!rules?.required; 19 | 20 | const renderChildren = (child: React.ReactElement) => { 21 | const { onChange, onBlur, value } = field; 22 | return React.cloneElement(child, { ...child.props, onChange, onBlur, value }); 23 | }; 24 | 25 | return ( 26 | 32 | {React.isValidElement(children) ? renderChildren(children) : children} 33 | 34 | ); 35 | }; 36 | 37 | export default FormItem; 38 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Form/FormList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useFieldArray, useFormContext } from 'react-hook-form'; 3 | import type { UseFieldArrayProps } from 'react-hook-form'; 4 | 5 | export interface FormListProps extends Omit { 6 | children?: (params: ReturnType) => React.ReactNode; 7 | } 8 | 9 | const FormList = ({ children, ...props }: FormListProps): JSX.Element => { 10 | const { control } = useFormContext(); 11 | const arrayReturn = useFieldArray({ control, ...props }); 12 | 13 | return <>{children?.(arrayReturn)}; 14 | }; 15 | 16 | export default FormList; 17 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Form/FormSubscribe.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useWatch, useFormContext } from 'react-hook-form'; 3 | import type { DeepPartialSkipArrayKey } from 'react-hook-form'; 4 | 5 | type ChildrenType = (changedValues: DeepPartialSkipArrayKey) => React.ReactNode; 6 | 7 | export interface FormSubscribeProps { 8 | to: any; 9 | children: ChildrenType; 10 | } 11 | 12 | const FormSubscribe = (props: FormSubscribeProps): JSX.Element => { 13 | const { control } = useFormContext(); 14 | const watch = useWatch({ control, name: props.to }); 15 | 16 | return <>{props.children(watch)}; 17 | }; 18 | 19 | export default FormSubscribe; 20 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Form/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Form 表单 3 | desc: 用于数据录入、校验,支持输入框、单选框、复选框、文件上传等类型。 4 | demo: /form 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 表单组件 11 | --- 12 | 13 | > Form 组件是基于[react-hook-form](https://react-hook-form.com/)的封装 14 | 15 | ## 引入 16 | 17 | ```js 18 | import { Form } from '@pingtou/rn-vant'; 19 | ``` 20 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Form/index.ts: -------------------------------------------------------------------------------- 1 | import { useWatch, useFieldArray } from 'react-hook-form'; 2 | import _Form from './Form'; 3 | import Item from './FormItem'; 4 | import List from './FormList'; 5 | import Subscribe from './FormSubscribe'; 6 | 7 | const Form = Object.assign(_Form, { Item, Subscribe, List, useWatch, useFieldArray }); 8 | 9 | export { Form }; 10 | export default Form; 11 | export type { FormProps, FormItemProps, FormInstance } from './type'; 12 | export type { FormSubscribeProps } from './FormSubscribe'; 13 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Grid/Grid.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View } from 'react-native'; 3 | import { useThemeFactory } from '../Theme'; 4 | import type { GridProps } from './type'; 5 | import { createStyle } from './style'; 6 | 7 | const Grid = (props: GridProps): JSX.Element => { 8 | const { style, children, border, gutter } = props; 9 | const { styles } = useThemeFactory(createStyle); 10 | 11 | return ( 12 | 13 | {React.Children.toArray(children) 14 | .filter(React.isValidElement) 15 | .map((child: React.ReactElement, index: number) => 16 | React.cloneElement(child, { 17 | index, 18 | parent: props, 19 | }) 20 | )} 21 | 22 | ); 23 | }; 24 | 25 | Grid.defaultProps = { 26 | center: true, 27 | border: true, 28 | columnNum: 4, 29 | }; 30 | 31 | export default Grid; 32 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Grid/index.ts: -------------------------------------------------------------------------------- 1 | import Grid from './Grid'; 2 | import GridItem from './GridItem'; 3 | 4 | const GridNamespace = Object.assign(Grid, { Item: GridItem }); 5 | export default GridNamespace; 6 | export { GridNamespace as Grid, GridItem }; 7 | export type { GridProps, GridItemProps, GridDirection } from './type'; 8 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Grid/type.ts: -------------------------------------------------------------------------------- 1 | import type { ViewProps, ViewStyle } from 'react-native'; 2 | import type { BadgeProps } from '../Badge/type'; 3 | 4 | export type GridDirection = 'horizontal' | 'vertical'; 5 | 6 | export interface GridProps extends ViewProps { 7 | /** 是否将格子固定为正方形 */ 8 | square?: boolean; 9 | /** 是否将格子内容居中显示 */ 10 | center?: boolean; 11 | /** 是否显示边框 */ 12 | border?: boolean; 13 | /** 格子之间的间距 */ 14 | gutter?: number; 15 | /** 是否调换图标和文本的位置 */ 16 | reverse?: boolean; 17 | /** 图标大小 */ 18 | iconSize?: number; 19 | /** 格子内容排列的方向,可选值为 `horizontal` */ 20 | direction?: GridDirection; 21 | /** 列数 */ 22 | columnNum?: number; 23 | } 24 | 25 | export interface GridItemProps extends ViewProps { 26 | /** 图标右上角徽标 */ 27 | badge?: BadgeProps; 28 | /** 文字 */ 29 | text?: string | React.ReactNode; 30 | /** 图标 */ 31 | icon?: React.ReactNode; 32 | /** 图标颜色,等同于 Icon 组件的 color 属性 */ 33 | iconColor?: string; 34 | contentStyle?: ViewStyle; 35 | onPress?: () => void; 36 | } 37 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Image/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Image 图片 3 | desc: 增强版的 img 标签,提供多种图片填充模式,支持图片懒加载、加载中提示、加载失败提示。 4 | demo: /image 5 | nav: 6 | path: / 7 | 8 | group: 9 | title: 基础组件 10 | --- 11 | 12 | ## 基础用法 13 | 14 | ```jsx 15 | { 18 | console.log('??'); 19 | }} 20 | /> 21 | ``` 22 | 23 | ## 填充模式 24 | 25 | ```jsx 26 | const resizeMode: ImageResizeMode[] = ['center', 'contain', 'cover', 'repeat', 'stretch']; 27 | 28 | 29 | {resizeMode.map(it => ( 30 | 31 | 32 | {it} 33 | 34 | ))} 35 | 36 | ``` 37 | 38 | ## 圆形图片 39 | 40 | 通过 `round` 属性可以设置图片变圆 41 | 42 | ```jsx 43 | 44 | ``` 45 | 46 | ## 加载中提示 47 | 48 | Image 组件提供了默认的加载中提示,支持通过 `loading` 自定义内容。 49 | 50 | ```jsx 51 | } 54 | /> 55 | ``` 56 | 57 | ## 加载失败提示 58 | 59 | Image 组件提供了默认的加载失败提示,支持通过 `alt` 自定义内容。 60 | 61 | ```jsx 62 | 加载失败 63 | ``` 64 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Image/index.ts: -------------------------------------------------------------------------------- 1 | import Image from './Image'; 2 | 3 | export { Image }; 4 | export default Image; 5 | export type { ImageProps } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ImagePicker/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ImagePicker 图片选择器 3 | desc: 用于将本地的图片上传至服务器,并在上传过程中展示预览图和上传进度。 4 | demo: /image-picker 5 | nav: 6 | path: / 7 | 8 | group: 9 | title: 表单组件 10 | --- 11 | 12 | ## 基础用法 13 | 14 | ```tsx 15 | import React from 'react'; 16 | import { ImagePicker } from '@pingtou/rn-vant'; 17 | 18 | const defaultValue = [ 19 | { 20 | url: 'https://img.yzcdn.cn/vant/sand.jpg', 21 | fileName: '图片名称', 22 | }, 23 | { 24 | url: 'https://img.yzcdn.cn/vant/tree.jpg', 25 | fileName: '图片名称', 26 | }, 27 | ]; 28 | 29 | export default () => { 30 | return ; 31 | }; 32 | ``` 33 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ImagePicker/index.ts: -------------------------------------------------------------------------------- 1 | import ImagePicker from './ImagePicker'; 2 | 3 | export default ImagePicker; 4 | export { ImagePicker }; 5 | export type { ImagePickerProps } from './types'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ImagePreview/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ImagePreview 图片预览 3 | desc: 图片预览,支持函数调用和组件调用两种方式。 4 | demo: /image-preview 5 | nav: 6 | path: / 7 | 8 | group: 9 | title: 展示组件 10 | --- 11 | 12 | ## 基础用法 13 | 14 | 直接传入图片数组,即可展示图片预览。 15 | 16 | ```jsx 17 | import React from 'react'; 18 | import { Cell, ImagePreview } from '@pingtou/rn-vant'; 19 | 20 | const images = [ 21 | 'https://img.yzcdn.cn/vant/apple-1.jpg', 22 | 'https://img.yzcdn.cn/vant/apple-2.jpg', 23 | 'https://img.yzcdn.cn/vant/apple-3.jpg', 24 | ]; 25 | 26 | export default () => { 27 | return ( 28 | { 32 | ImagePreview.open({ 33 | images, 34 | onChange: index => console.log(`当前展示第${index + 1}张`), 35 | }); 36 | }} 37 | /> 38 | ); 39 | }; 40 | ``` 41 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ImagePreview/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ImagePreviewInner from './ImagePreview'; 3 | import { PortalRef } from '../ConfigProvider'; 4 | import type { ImagePreviewProps } from './type'; 5 | 6 | let currentKey = 0; 7 | 8 | const openImagePreview = (options: Omit) => { 9 | const key = `image_preview_${++currentKey}`; 10 | 11 | const handleClosed = () => { 12 | PortalRef.current?.removePortal(key); 13 | options.onClosed?.(); 14 | }; 15 | 16 | const renderImagePreview = () => ( 17 | 18 | ); 19 | 20 | PortalRef.current?.addPortal(key, renderImagePreview()); 21 | 22 | return { close: handleClosed }; 23 | }; 24 | 25 | const ImagePreview = Object.assign(ImagePreviewInner, { open: openImagePreview }); 26 | 27 | export { ImagePreview }; 28 | export default ImagePreview; 29 | export type { ImagePreviewProps, ImagePreviewItemProps } from './type'; 30 | -------------------------------------------------------------------------------- /packages/rn-vant/src/ImagePreview/type.ts: -------------------------------------------------------------------------------- 1 | export type CloseParams = { url: string; index: number }; 2 | 3 | type CouldClose = boolean | Promise; 4 | 5 | export interface ImagePreviewProps { 6 | visible?: boolean; 7 | overlay?: boolean; 8 | // lazyload?: LazyImageType; 9 | maxZoom?: number; 10 | closeable?: boolean; 11 | showIndicators?: boolean; 12 | showIndex?: boolean; 13 | indexRender?: ({ index, len }: { index: number; len: number }) => React.ReactNode; 14 | beforeClose?: (active: string | number) => CouldClose; 15 | onClose?: (p?: CloseParams) => void; 16 | onClosed?: () => void; 17 | onChange?: (index: number) => void; 18 | images?: string[]; 19 | swipeDuration?: number; 20 | startPosition?: number; 21 | closeIcon?: React.ReactNode; 22 | /** 只在点击关闭按钮时关闭ImagePreview组件 */ 23 | closeOnlyClickCloseIcon?: boolean; 24 | testID?: string; 25 | } 26 | 27 | export interface ImagePreviewItemProps { 28 | // lazyload: LazyImageType; 29 | image: string; 30 | maxZoom: number; 31 | onTap: () => void; 32 | onZoomChange?: (zoom: number) => void; 33 | } 34 | -------------------------------------------------------------------------------- /packages/rn-vant/src/IndexBar/IndexBarContext.ts: -------------------------------------------------------------------------------- 1 | import { createContext, Context } from 'react'; 2 | 3 | export interface IndexBarContextState { 4 | zIndex?: number | string; 5 | highlightColor?: string; 6 | sticky?: boolean; 7 | } 8 | 9 | const IndexBarContext: Context = createContext({}); 10 | 11 | export default IndexBarContext; 12 | -------------------------------------------------------------------------------- /packages/rn-vant/src/IndexBar/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: IndexBar 索引栏 3 | desc: 用于列表的索引分类显示和快速定位。 4 | demo: /index-bar 5 | nav: 6 | path: / 7 | 8 | group: 9 | title: 导航组件 10 | --- 11 | 12 | ## 基础用法 13 | -------------------------------------------------------------------------------- /packages/rn-vant/src/IndexBar/index.ts: -------------------------------------------------------------------------------- 1 | import _IndexBar from './IndexBar'; 2 | import IndexAnchor from './IndexAnchor'; 3 | 4 | const IndexBar = Object.assign(_IndexBar, { Anchor: IndexAnchor }); 5 | 6 | export default IndexBar; 7 | export { IndexBar, IndexAnchor }; 8 | export type { IndexBarProps, IndexBarInstance, IndexAnchorProps } from './types'; 9 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Input/Input.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from 'react'; 2 | import BaseInput from './BaseInput'; 3 | import type { InputProps, InputInstance } from './type'; 4 | 5 | const Input = forwardRef((props, ref) => ( 6 | 7 | )); 8 | 9 | export default Input; 10 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Input/TextArea.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from 'react'; 2 | import { View, Text } from 'react-native'; 3 | import isFunction from 'lodash-es/isFunction'; 4 | import { useControllableValue } from '../hooks'; 5 | import { useThemeFactory } from '../Theme'; 6 | import BaseInput from './BaseInput'; 7 | import { createTextAreaStyle } from './style'; 8 | import type { TextAreaProps, InputInstance } from './type'; 9 | 10 | const TextArea = forwardRef((props, ref) => { 11 | const { showWordLimit = false, maxLength, rows = 2 } = props; 12 | const [value, setValue] = useControllableValue(props); 13 | const { styles } = useThemeFactory(createTextAreaStyle); 14 | 15 | const renderWordLimit = () => { 16 | const count = (value ? `${value}` : '').length; 17 | 18 | if (isFunction(showWordLimit)) return showWordLimit({ currentCount: count, maxLength }); 19 | 20 | if (maxLength) return `${count}/${maxLength}`; 21 | 22 | return null; 23 | }; 24 | 25 | return ( 26 | 27 | 28 | {!!showWordLimit && {renderWordLimit()}} 29 | 30 | ); 31 | }); 32 | 33 | export default TextArea; 34 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Input/index.ts: -------------------------------------------------------------------------------- 1 | import _Input from './Input'; 2 | import TextArea from './TextArea'; 3 | 4 | const Input = Object.assign(_Input, { TextArea }); 5 | 6 | export default Input; 7 | export { Input }; 8 | export type { 9 | InputProps, 10 | InputInstance, 11 | TextAreaProps, 12 | InputTextAlign, 13 | InputSharedProps, 14 | } from './type'; 15 | -------------------------------------------------------------------------------- /packages/rn-vant/src/KeyboardSpace/index.ts: -------------------------------------------------------------------------------- 1 | import KeyboardSpace from './KeyboardSpace'; 2 | 3 | export default KeyboardSpace; 4 | export { KeyboardSpace }; 5 | export type { KeyboardSpaceProps } from './KeyboardSpace'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Layout/Col.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, useContext } from 'react'; 2 | import { View, ViewStyle } from 'react-native'; 3 | import RowContext from './RowContext'; 4 | 5 | interface Props { 6 | /** 7 | * 列元素宽度 8 | */ 9 | span?: number; 10 | /** 11 | * 列元素偏移距离 12 | */ 13 | offset?: number; 14 | /** 15 | * 组件样式 16 | */ 17 | style?: ViewStyle; 18 | } 19 | 20 | const getPercent = (count?: number) => (count ? `${(count / 24) * 100}%` : undefined); 21 | 22 | const LayoutCol: FC = ({ span, offset, style, children }) => { 23 | const { gutter } = useContext(RowContext); 24 | 25 | const mergedStyle: ViewStyle = gutter 26 | ? { 27 | paddingLeft: gutter / 2, 28 | paddingRight: gutter / 2, 29 | } 30 | : {}; 31 | 32 | return ( 33 | 34 | {children} 35 | 36 | ); 37 | }; 38 | 39 | LayoutCol.displayName = 'Layout.Col'; 40 | 41 | export default LayoutCol; 42 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Layout/RowContext.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | 3 | export interface RowContextState { 4 | gutter?: number; 5 | } 6 | 7 | const RowContext = createContext({}); 8 | 9 | export default RowContext; 10 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Layout/index.ts: -------------------------------------------------------------------------------- 1 | import LayoutRow from './Row'; 2 | import LayoutCol from './Col'; 3 | 4 | export interface LayoutProps { 5 | Row: typeof LayoutRow; 6 | Col: typeof LayoutCol; 7 | } 8 | 9 | export const Layout: LayoutProps = { Row: LayoutRow, Col: LayoutCol }; 10 | 11 | export default Layout; 12 | -------------------------------------------------------------------------------- /packages/rn-vant/src/LinearGradient/index.ts: -------------------------------------------------------------------------------- 1 | import LinearGradient from './LinearGradient'; 2 | import type { LinearGradientProps } from './types'; 3 | 4 | export default LinearGradient; 5 | export { LinearGradient, LinearGradientProps }; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/LinearGradient/types.ts: -------------------------------------------------------------------------------- 1 | import type { ViewProps, ColorValue } from 'react-native'; 2 | 3 | export interface LinearGradientProps extends ViewProps { 4 | colors: ColorValue[]; 5 | start?: { x: number; y: number }; 6 | end?: { x: number; y: number }; 7 | locations?: number[]; 8 | } 9 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Loading/Loading.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, memo } from 'react'; 2 | import { View, Text } from 'react-native'; 3 | import { useThemeFactory } from '../Theme'; 4 | import Circular from './Circular'; 5 | import Spinner from './Spinner'; 6 | import type { LoadingProps } from './type'; 7 | import { createStyle } from './style'; 8 | 9 | const Loading: FC = props => { 10 | const { styles, theme } = useThemeFactory(createStyle); 11 | const { 12 | children, 13 | size = 30, 14 | type = 'circular', 15 | vertical, 16 | textColor, 17 | textSize, 18 | style, 19 | color = theme.gray_5, 20 | ...rest 21 | } = props; 22 | 23 | return ( 24 | 28 | {type === 'circular' ? ( 29 | 30 | ) : ( 31 | 32 | )} 33 | {children && ( 34 | 40 | {children} 41 | 42 | )} 43 | 44 | ); 45 | }; 46 | 47 | export default memo(Loading); 48 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Loading/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Loading 加载 3 | desc: 加载图标,用于表示加载中的过渡状态。 4 | demo: /loading 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 反馈组件 11 | --- 12 | 13 | ## 加载类型 14 | 15 | 通过 `type` 属性可以设置加载图标的类型,默认为 `circular`,可选值为 `spinner`。 16 | 17 | ```jsx 18 | 19 | 20 | 21 | ``` 22 | 23 | ## 自定义颜色 24 | 25 | 通过 `color` 属性设置加载图标的颜色。 26 | 27 | ```jsx 28 | 29 | 30 | 31 | ``` 32 | 33 | ## 单元格大小 34 | 35 | 通过 size 属性可以控制单元格的大小。 36 | 37 | ```jsx 38 | 39 | 40 | ``` 41 | 42 | ## 自定义大小 43 | 44 | 通过 `size` 属性设置加载图标的大小。 45 | 46 | ```jsx 47 | 48 | 49 | 50 | ``` 51 | 52 | ## 加载文案 53 | 54 | ```jsx 55 | 56 | 加载中... 57 | 58 | ``` 59 | 60 | ## 垂直排列 61 | 62 | 设置 `vertical` 属性后,图标和文案会垂直排列。 63 | 64 | ```jsx 65 | 66 | 加载中... 67 | 68 | ``` 69 | 70 | ## 自定义文案颜色 71 | 72 | 通过 `color` 或者 `textColor` 属性设置加载文案的颜色。 73 | 74 | ```jsx 75 | 76 | 加载中... 77 | 78 | 79 | 加载中... 80 | 81 | ``` 82 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Loading/index.ts: -------------------------------------------------------------------------------- 1 | import Loading from './Loading'; 2 | 3 | export default Loading; 4 | export { Loading }; 5 | export type { LoadingProps } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Loading/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | export const createStyle = (theme: DiceUI.Theme) => { 4 | const textFontSize = theme.font_size_md; 5 | 6 | return StyleSheet.create({ 7 | text: { 8 | fontSize: textFontSize, 9 | marginLeft: theme.padding_xs, 10 | }, 11 | verticalText: { 12 | fontSize: textFontSize, 13 | marginTop: theme.padding_xs, 14 | }, 15 | }); 16 | }; 17 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Loading/type.ts: -------------------------------------------------------------------------------- 1 | import type { ViewProps } from 'react-native'; 2 | 3 | export type LoadingType = 'spinner' | 'circular'; 4 | 5 | export interface LoadingProps extends ViewProps { 6 | /** 7 | * 颜色 8 | * @default #c8c9cc 9 | */ 10 | color?: string; 11 | /** 12 | * 加载图标大小 13 | * @default 30 14 | */ 15 | size?: number; 16 | /** 17 | * 类型 18 | * @default circular 19 | */ 20 | type?: LoadingType; 21 | /** 22 | * 文字大小 23 | */ 24 | textSize?: number; 25 | /** 26 | * 文字颜色 27 | * @default #c8c9cc 28 | */ 29 | textColor?: string; 30 | /** 31 | * 是否垂直排列图标和文字内容 32 | * @default false 33 | */ 34 | vertical?: boolean; 35 | } 36 | 37 | export interface LoadingIconProps { 38 | color: string; 39 | size: number; 40 | } 41 | -------------------------------------------------------------------------------- /packages/rn-vant/src/NavBar/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: NavBar 导航栏 3 | desc: 为页面提供导航功能,常用于页面顶部。 4 | demo: /nav-bar 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 导航组件 11 | --- 12 | 13 | ### 基础用法 14 | 15 | ```jsx 16 | Toast.message('返回')} 22 | onPressRight={() => Toast.message('按钮')} 23 | /> 24 | ``` 25 | 26 | ### 自定义内容 27 | 28 | 自定义导航栏两侧的内容。 29 | 30 | ```jsx 31 | Toast.message('返回')} 36 | rightText={} 37 | onPressRight={() => Toast.message('按钮')} 38 | /> 39 | ``` 40 | -------------------------------------------------------------------------------- /packages/rn-vant/src/NavBar/index.ts: -------------------------------------------------------------------------------- 1 | import NavBar from './NavBar'; 2 | 3 | export default NavBar; 4 | export { NavBar }; 5 | export type { NavBarProps } from './interface'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/NavBar/interface.ts: -------------------------------------------------------------------------------- 1 | import type { ViewStyle, StyleProp, TextStyle } from 'react-native'; 2 | 3 | export type LoadingType = 'circular' | 'spinner'; 4 | 5 | export interface NavBarProps { 6 | /** 7 | * 最外层的样式 8 | */ 9 | style?: StyleProp; 10 | 11 | /** 12 | * 左箭头样式 13 | */ 14 | leftArrowStyle?: StyleProp; 15 | 16 | /** 17 | * 标题样式 18 | */ 19 | titleTextStyle?: StyleProp; 20 | /** 21 | * 标题 22 | */ 23 | title?: React.ReactNode; 24 | /** 25 | * 左侧文案 26 | */ 27 | leftText?: React.ReactNode; 28 | /** 29 | * 右侧文案 30 | */ 31 | rightText?: React.ReactNode; 32 | /** 33 | * 是否显示左侧箭头 34 | * @default true 35 | */ 36 | leftArrow?: boolean; 37 | /** 38 | * 是否开启顶部安全区适配 39 | */ 40 | safeAreaInsetTop?: boolean; 41 | /** 42 | * 是否显示下边框 43 | * @default true 44 | */ 45 | border?: boolean; 46 | onPressLeft?: () => void; 47 | onPressRight?: () => void; 48 | } 49 | -------------------------------------------------------------------------------- /packages/rn-vant/src/NoticeBar/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: NoticeBar 通知栏 3 | desc: 用于循环播放展示一组消息通知。 4 | demo: /notice-bar 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 展示组件 11 | --- 12 | 13 | ### 基础用法 14 | 15 | 通过 `text` 属性设置通知栏的内容,通过 `leftIcon` 属性设置通知栏左侧的图标。 16 | 17 | ```jsx 18 | 19 | ``` 20 | 21 | ### 滚动播放 22 | 23 | 通知栏的内容长度溢出时会自动打点,通过 `scrollable` 属性可以控制内容长度溢出时自动滚动。 24 | 25 | ```jsx 26 | 27 | ``` 28 | 29 | ### 多行展示 30 | 31 | 文字较长时,可以通过设置 `wrapable` 属性来开启多行展示。 32 | 33 | ```jsx 34 | 35 | ``` 36 | 37 | ### 通知栏模式 38 | 39 | 通知栏支持 `closeable` 和 `link` 两种模式。 40 | 41 | ```jsx 42 | 43 | 技术是开发它的人的共同灵魂。 44 | 45 | 46 | 技术是开发它的人的共同灵魂。 47 | ``` 48 | 49 | ### 自定义样式 50 | 51 | 通过 `color` 属性设置文本颜色,通过 `background` 属性设置背景色。 52 | 53 | ```jsx 54 | 60 | ``` 61 | -------------------------------------------------------------------------------- /packages/rn-vant/src/NoticeBar/index.ts: -------------------------------------------------------------------------------- 1 | import NoticeBar from './NoticeBar'; 2 | 3 | export default NoticeBar; 4 | export { NoticeBar }; 5 | export type { NoticeBarProps, NoticeBarMode, NoticeBarInstance } from './interface'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/NoticeBar/interface.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { ViewStyle, StyleProp } from 'react-native'; 3 | 4 | export type NoticeBarMode = '' | 'closeable' | 'link'; 5 | 6 | export type NoticeBarInstance = { 7 | /** 重置通知栏到初始状态 */ 8 | reset: () => void; 9 | }; 10 | 11 | export interface NoticeBarProps { 12 | /** 13 | * 最外层的样式 14 | */ 15 | style?: StyleProp; 16 | 17 | /** 18 | * 通知栏模式 19 | */ 20 | mode?: NoticeBarMode; 21 | /** 22 | * 左侧图标名称或图片链接 23 | */ 24 | leftIcon?: string | React.ReactNode; 25 | rightIcon?: string | React.ReactNode; 26 | /** 27 | * 滚动条背景 28 | */ 29 | background?: string; 30 | /** 31 | * 通知文本颜色 32 | */ 33 | color?: string; 34 | /** 35 | * 通知文本内容 36 | */ 37 | text?: React.ReactNode; 38 | /** 39 | * 是否开启滚动播放,内容长度溢出时默认开启 40 | */ 41 | scrollable?: boolean; 42 | /** 43 | * 是否开启文本换行,只在禁用滚动时生效 44 | */ 45 | wrapable?: boolean; 46 | /** 47 | * 滚动速率 (px/s) 48 | * @default 60 49 | */ 50 | speed?: number; 51 | /** 52 | * 动画延迟时间 (ms) 53 | * @default 1000 54 | */ 55 | delay?: number; 56 | /** 57 | * 关闭通知栏时触发 58 | */ 59 | onClose?: () => void; 60 | /** 61 | * 点击通知栏时触发 62 | */ 63 | onPress?: () => void; 64 | /** 65 | * 每当滚动栏重新开始滚动时触发 66 | */ 67 | onReplay?: () => void; 68 | children?: React.ReactNode; 69 | } 70 | -------------------------------------------------------------------------------- /packages/rn-vant/src/NoticeBar/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | export const createStyle = (theme: DiceUI.Theme) => { 4 | return StyleSheet.create({ 5 | content: { 6 | color: theme.notice_bar_text_color, 7 | fontSize: theme.notice_bar_font_size, 8 | }, 9 | 10 | leftIcon: { 11 | minWidth: theme.notice_bar_icon_min_width, 12 | }, 13 | 14 | noWrapable: { 15 | height: theme.notice_bar_height, 16 | paddingHorizontal: theme.notice_bar_padding_horizontal, 17 | paddingVertical: theme.notice_bar_padding_vertical, 18 | }, 19 | 20 | rightIcon: { 21 | justifyContent: 'flex-end', 22 | minWidth: theme.notice_bar_icon_min_width, 23 | }, 24 | 25 | wrap: { 26 | flex: 1, 27 | overflow: 'hidden', 28 | }, 29 | 30 | wrapable: { 31 | paddingHorizontal: theme.notice_bar_wrapable_padding_horizontal, 32 | paddingVertical: theme.notice_bar_wrapable_padding_vertical, 33 | }, 34 | 35 | wrapper: { 36 | alignItems: 'center', 37 | backgroundColor: theme.notice_bar_background_color, 38 | flexDirection: 'row', 39 | overflow: 'hidden', 40 | }, 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Notify/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import constants from '../utils/constants'; 3 | 4 | export const createStyle = (theme: DiceUI.Theme) => { 5 | return StyleSheet.create({ 6 | danger: { 7 | backgroundColor: theme.notify_danger_background_color, 8 | }, 9 | notify: { 10 | alignItems: 'center', 11 | flexDirection: 'row', 12 | justifyContent: 'center', 13 | paddingHorizontal: theme.notify_padding_horizontal, 14 | paddingVertical: theme.notify_padding_vertical, 15 | width: constants.screenWidth, 16 | }, 17 | primary: { 18 | backgroundColor: theme.notify_primary_background_color, 19 | }, 20 | success: { 21 | backgroundColor: theme.notify_success_background_color, 22 | }, 23 | text: { 24 | color: theme.notify_text_color, 25 | fontSize: theme.notify_font_size, 26 | lineHeight: theme.notify_line_height, 27 | }, 28 | warning: { 29 | backgroundColor: theme.notify_warning_background_color, 30 | }, 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /packages/rn-vant/src/NumberKeyboard/SlideAnimatable.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import type { View, ViewProps } from 'react-native'; 3 | import * as Animatable from 'react-native-animatable'; 4 | import { useUpdateEffect, useLayout } from '../hooks'; 5 | 6 | interface SlideAnimatableProps extends Pick { 7 | visible: boolean; 8 | duration: number; 9 | } 10 | 11 | const SlideAnimatable: React.FC = ({ 12 | children, 13 | style, 14 | visible, 15 | duration, 16 | }) => { 17 | const handleViewRef = useRef(null); 18 | const [layout, onLayout] = useLayout(); 19 | 20 | useUpdateEffect(() => { 21 | if (visible) { 22 | handleViewRef.current?.transition?.( 23 | { translateY: layout.height }, 24 | { translateY: 0 }, 25 | duration 26 | ); 27 | } else { 28 | handleViewRef.current?.transitionTo?.({ translateY: layout.height }, duration); 29 | } 30 | }, [visible]); 31 | 32 | return ( 33 | 34 | {children} 35 | 36 | ); 37 | }; 38 | 39 | export default SlideAnimatable; 40 | -------------------------------------------------------------------------------- /packages/rn-vant/src/NumberKeyboard/index.ts: -------------------------------------------------------------------------------- 1 | import NumberKeyboard from './NumberKeyboard'; 2 | 3 | export default NumberKeyboard; 4 | export { NumberKeyboard }; 5 | export type { KeyType, NumberKeyboardTheme, KeyConfig, NumberKeyboardProps } from './types'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Overlay/index.ts: -------------------------------------------------------------------------------- 1 | import Overlay from './Overlay'; 2 | 3 | export default Overlay; 4 | export { Overlay }; 5 | export type { OverlayProps } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Overlay/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | export const createStyle = (theme: DiceUI.Theme) => { 4 | return StyleSheet.create({ 5 | backdrop: { 6 | ...StyleSheet.absoluteFillObject, 7 | backgroundColor: theme.overlay_background_color, 8 | }, 9 | container: { 10 | ...StyleSheet.absoluteFillObject, 11 | alignItems: 'center', 12 | justifyContent: 'center', 13 | }, 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Overlay/type.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { StyleProp, ViewStyle } from 'react-native'; 3 | 4 | export type OverlayProps = { 5 | // 是否展示遮罩层 6 | visible?: boolean; 7 | // 背景容器的样式 8 | backdropStyle?: StyleProp; 9 | // 叠加在背景容器上的组件的样式 10 | overlayStyle?: StyleProp; 11 | // 背景是否透明 12 | transparent?: boolean; 13 | // 动画时长 14 | duration?: number; 15 | children?: React.ReactNode; 16 | // 点击背景容器时触发的事件 17 | onBackdropPress?: () => void; 18 | onPress?: () => void; 19 | // 动画结束后触发的事件 20 | onFadeDone?: () => void; 21 | }; 22 | -------------------------------------------------------------------------------- /packages/rn-vant/src/PanningViews/asPanViewConsumer.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component, Ref } from 'react'; 2 | import PanningContext from './PanningContext'; 3 | 4 | function asPanViewConsumer( 5 | WrappedComponent: React.ComponentType 6 | ): React.ComponentClass { 7 | class PanViewConsumer extends Component { 8 | contentRef: any; 9 | 10 | saveRef = (r: Ref>) => { 11 | this.contentRef = r; 12 | }; 13 | 14 | render() { 15 | return ( 16 | 17 | {context => } 18 | 19 | ); 20 | } 21 | } 22 | 23 | return PanViewConsumer as any; 24 | } 25 | 26 | export default asPanViewConsumer; 27 | -------------------------------------------------------------------------------- /packages/rn-vant/src/PanningViews/index.ts: -------------------------------------------------------------------------------- 1 | export { default as PanDismissibleView } from './PanDismissibleView'; 2 | export { default as PanGestureView } from './PanGestureView'; 3 | export { default as PanListenerView } from './PanListenerView'; 4 | export { default as PanResponderView } from './PanResponderView'; 5 | export { default as PanningContext } from './PanningContext'; 6 | export { default as PanningProvider } from './PanningProvider'; 7 | 8 | export type { 9 | PanningDirections, 10 | PanLocationProps, 11 | PanDirectionsProps, 12 | PanningContextState, 13 | PanAmountsProps, 14 | } from './PanningContext'; 15 | -------------------------------------------------------------------------------- /packages/rn-vant/src/PasswordInput/PasswordInput.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View } from 'react-native'; 3 | import { useThemeFactory } from '../Theme'; 4 | import type { PasswordInputProps, PasswordInputInstance } from './types'; 5 | import { createStyle } from './style'; 6 | 7 | const PasswordInput = React.forwardRef(() => { 8 | const { styles } = useThemeFactory(createStyle); 9 | 10 | return ; 11 | }); 12 | 13 | export default PasswordInput; 14 | -------------------------------------------------------------------------------- /packages/rn-vant/src/PasswordInput/index.ts: -------------------------------------------------------------------------------- 1 | import PasswordInput from './PasswordInput'; 2 | 3 | export { PasswordInput }; 4 | export type { PasswordInputProps } from './types'; 5 | -------------------------------------------------------------------------------- /packages/rn-vant/src/PasswordInput/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet, ViewStyle } from 'react-native'; 2 | import type { Vars } from '../styles'; 3 | 4 | export const passwordInputDefaultVars = (vars: Vars) => ({ 5 | password_input_height: 50, 6 | password_input_margin_vertical: 0, 7 | password_input_margin_horizontal: vars.padding_md, 8 | password_input_font_size: 20, 9 | password_input_border_radius: 6, 10 | password_input_background_color: vars.white, 11 | password_input_info_color: vars.gray_6, 12 | password_input_info_font_size: vars.font_size_md, 13 | password_input_error_info_color: vars.danger_color, 14 | password_input_dot_size: 10, 15 | password_input_dot_color: vars.black, 16 | password_input_text_color: vars.text_color, 17 | password_input_cursor_color: vars.text_color, 18 | password_input_cursor_width: 1, 19 | password_input_cursor_height: '40%', 20 | password_input_cursor_animation_duration: 1, 21 | password_input_item_border_radius: 0, 22 | }); 23 | 24 | interface Styles { 25 | wrapper: ViewStyle; 26 | } 27 | 28 | export const createStyle = (theme: DiceUI.Theme): Styles => { 29 | return StyleSheet.create({ 30 | wrapper: { 31 | marginHorizontal: theme.password_input_margin_horizontal, 32 | marginVertical: theme.password_input_margin_vertical, 33 | position: 'relative', 34 | }, 35 | }); 36 | }; 37 | -------------------------------------------------------------------------------- /packages/rn-vant/src/PasswordInput/types.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | 3 | export interface PasswordInputProps { 4 | /** 默认值 */ 5 | value?: string; 6 | /** 输入框下方文字提示 */ 7 | info?: React.ReactNode; 8 | /** 输入框下方错误提示 */ 9 | errorInfo?: React.ReactNode; 10 | /** 输入框格子之间的间距 */ 11 | gutter?: number; 12 | /** 输入框类型, ['number', 'text] */ 13 | type?: string; 14 | /** 密码最大长度 */ 15 | length?: number; 16 | /** 自动聚焦 */ 17 | autoFocus?: boolean; 18 | /** 是否隐藏密码内容 */ 19 | mask?: boolean; 20 | /** 输入校验规则 */ 21 | validator?: () => void; 22 | /** 高亮样式 */ 23 | highlightClass?: string; 24 | /** 密码change事件 */ 25 | onChange?: (v: string) => void; 26 | /** 密码提交事件(位数满了自动提交) */ 27 | onSubmit?: (v: string) => void; 28 | /** 输入框聚焦时触发 */ 29 | onFocus?: (e: React.FocusEvent) => void; 30 | onBlur?: (e: React.FocusEvent) => void; 31 | } 32 | 33 | export type PasswordInputInstance = { 34 | focus: () => void; 35 | blur: () => void; 36 | clear: () => void; 37 | }; 38 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Picker/index.ts: -------------------------------------------------------------------------------- 1 | import Picker from './Picker'; 2 | 3 | export { Picker }; 4 | export default Picker; 5 | export type { PickerProps, PickerOption, PickerFieldNames, PickerToolbarPosition } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Popover/index.ts: -------------------------------------------------------------------------------- 1 | import Popover from './Popover'; 2 | 3 | export { Popover }; 4 | export type { 5 | PopoverProps, 6 | PopoverPlacement, 7 | PopoverTheme, 8 | PopoverInstance, 9 | PopoverAction, 10 | } from './type'; 11 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Popup/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Popup 弹出层 3 | desc: 弹出层容器,用于展示弹窗、信息提示等内容,支持多个弹出层叠加展示。 4 | demo: /popup 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 基础组件 11 | --- 12 | 13 | ## 基础用法 14 | 15 | 通过 `visible` 控制弹出层是否展示。 16 | 17 | ```jsx 18 | import React, { useState } from 'react'; 19 | import { Popup } from '@pingtou/rn-vant'; 20 | 21 | export default () => { 22 | const [visible, setVisible] = useState(false); 23 | 24 | return ( 25 | 26 | demo 27 | 28 | ); 29 | } 30 | ``` 31 | 32 | ## 弹出位置 33 | 34 | 通过 `position` 属性设置弹出位置,默认居中弹出,可以设置为 `top`、`bottom`、`left`、`right`。 35 | 36 | ```jsx 37 | 38 | demo 39 | 40 | ``` 41 | 42 | ## 关闭图标 43 | 44 | 设置 `closeable` 属性后,会在弹出层的右上角显示关闭图标,并且可以通过 `closeIcon` 属性自定义图标,使用 `closeIconPosition` 属性可以自定义图标位置。 45 | 46 | ```jsx 47 | 54 | demo 55 | 56 | ``` 57 | 58 | ## 圆角弹窗 59 | 60 | 设置 `round` 属性后,弹窗会根据弹出位置添加不同的圆角样式。 61 | 62 | ```jsx 63 | 64 | demo 65 | 66 | ``` 67 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Popup/index.ts: -------------------------------------------------------------------------------- 1 | import Popup from './Popup'; 2 | 3 | export { Popup }; 4 | export default Popup; 5 | export type { PopupProps, PopupPosition, PopupCloseIconPosition } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Portal/index.tsx: -------------------------------------------------------------------------------- 1 | export * from '@gorhom/portal'; 2 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Progress/Progress.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef, useState } from 'react'; 2 | import { View, Text } from 'react-native'; 3 | import type { LayoutChangeEvent } from 'react-native'; 4 | import { useThemeFactory } from '../Theme'; 5 | import type { ProgressProps } from './type'; 6 | import { createStyle } from './style'; 7 | 8 | const Progress = forwardRef((props, ref) => { 9 | const { style, percentage = 0, showPivot = true, pivotText, ...extra } = props; 10 | const { styles } = useThemeFactory(createStyle, { ...extra, percentage }); 11 | const [pivotWidth, setPivotWidth] = useState(0); 12 | 13 | // 获取进度文字的宽度 14 | const onPivotLayout = (event: LayoutChangeEvent) => { 15 | setPivotWidth(event.nativeEvent.layout.width); 16 | }; 17 | 18 | return ( 19 | 20 | 21 | {showPivot && ( 22 | 26 | {pivotText ?? `${percentage}%`} 27 | 28 | )} 29 | 30 | ); 31 | }); 32 | 33 | Progress.displayName = 'Progress'; 34 | 35 | export default Progress; 36 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Progress/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Progress 进度条 3 | desc: 用于展示操作的当前进度。 4 | demo: /progress 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 展示组件 11 | --- 12 | 13 | ## 基础用法 14 | 15 | 进度条默认为蓝色,使用 `percentage` 属性来设置当前进度。 16 | 17 | ```jsx 18 | 19 | ``` 20 | 21 | ## 线条粗细 22 | 23 | 通过 `strokeWidth` 可以设置进度条的粗细。 24 | 25 | ```jsx 26 | 27 | ``` 28 | 29 | ## 置灰 30 | 31 | 设置 `inactive` 属性后进度条将置灰。 32 | 33 | ```jsx 34 | 35 | ``` 36 | 37 | ## 样式定制 38 | 39 | 可以使用 `pivotText` 属性自定义文字,`color` 属性自定义进度条颜色。 40 | 41 | ```jsx 42 | 43 | 44 | 50 | ``` 51 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Progress/index.ts: -------------------------------------------------------------------------------- 1 | import Progress from './Progress'; 2 | 3 | export default Progress; 4 | export { Progress }; 5 | export type { ProgressProps } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Progress/type.ts: -------------------------------------------------------------------------------- 1 | import type { StyleProp, ViewStyle } from 'react-native'; 2 | 3 | export interface ProgressProps { 4 | style?: StyleProp; 5 | /** 6 | * 进度条颜色 7 | */ 8 | color?: string; 9 | /** 10 | * 是否置灰 11 | */ 12 | inactive?: boolean; 13 | /** 14 | * 进度文字内容 15 | */ 16 | pivotText?: React.ReactNode; 17 | /** 18 | * 进度文字颜色 19 | */ 20 | textColor?: string; 21 | /** 22 | * 是否显示进度文字 23 | */ 24 | showPivot?: boolean; 25 | /** 26 | * 进度文字背景色 27 | */ 28 | pivotColor?: string; 29 | /** 30 | * 轨道颜色 31 | */ 32 | trackColor?: string; 33 | /** 34 | * 进度条粗细 35 | */ 36 | strokeWidth?: number; 37 | /** 38 | * 进度百分比 39 | */ 40 | percentage?: number; 41 | } 42 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Radio/context.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { StyleProp, ViewStyle } from 'react-native'; 3 | 4 | export type RadioValueType = string | number | boolean; 5 | 6 | export interface RadioOptionType { 7 | label: React.ReactNode; 8 | value: RadioValueType; 9 | style?: StyleProp; 10 | disabled?: boolean; 11 | onChange?: () => void; 12 | } 13 | export interface RadioGroupContext { 14 | toggleOption?: (option: RadioOptionType) => void; 15 | value?: any; 16 | disabled?: boolean; 17 | } 18 | 19 | export const GroupContext = React.createContext(null); 20 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Radio/index.style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | const createStyle = (theme: DiceUI.Theme) => { 4 | return StyleSheet.create({ 5 | icon: { 6 | alignItems: 'center', 7 | borderColor: theme.radio_icon_border_color, 8 | borderWidth: 1, 9 | justifyContent: 'center', 10 | }, 11 | iconChecked: { 12 | backgroundColor: theme.radio_checked_icon_color, 13 | borderColor: theme.radio_checked_icon_color, 14 | }, 15 | iconDisabled: { 16 | backgroundColor: theme.radio_disabled_background_color, 17 | borderColor: theme.radio_disabled_icon_color, 18 | }, 19 | label: { 20 | color: theme.radio_label_color, 21 | }, 22 | labelContainer: { 23 | marginLeft: theme.radio_label_margin, 24 | }, 25 | labelDisabled: { 26 | color: theme.radio_disabled_label_color, 27 | }, 28 | radio: { 29 | alignItems: 'center', 30 | flexDirection: 'row', 31 | }, 32 | }); 33 | }; 34 | 35 | export default createStyle; 36 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Radio/index.ts: -------------------------------------------------------------------------------- 1 | import InternalRadio from './Radio'; 2 | import Group from './Group'; 3 | 4 | export type { RadioProps } from './Radio'; 5 | export type { RadioGroupProps } from './Group'; 6 | export type { RadioOptionType } from './context'; 7 | 8 | type RadioType = typeof InternalRadio; 9 | 10 | interface RadioProps extends RadioType { 11 | Group: typeof Group; 12 | __ANT_CHECKBOX: boolean; 13 | } 14 | 15 | export const Radio = InternalRadio as RadioProps; 16 | 17 | Radio.Group = Group; 18 | Radio.__ANT_CHECKBOX = true; 19 | 20 | export default Radio; 21 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Rate/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Rate 评分 3 | desc: 用于对事物进行评级操作。 4 | demo: /rate 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 表单组件 11 | --- 12 | 13 | ## 基础用法 14 | 15 | 通过 `value` 来绑定当前评分值。 16 | 17 | ```jsx 18 | 19 | ``` 20 | 21 | ```jsx 22 | export default () => { 23 | const [value, setValue] = useState(3); 24 | return setValue(current)} />; 25 | }; 26 | ``` 27 | 28 | ## 自定义图标 29 | 30 | 通过 `icon` 属性设置选中时的图标,`voidIcon` 属性设置未选中时的图标。 31 | 32 | ```jsx 33 | 34 | ``` 35 | 36 | ## 自定义样式 37 | 38 | 通过 `size` 属性设置图标大小,`color` 属性设置选中时的颜色,`voidColor` 设置未选中时的颜色。 39 | 40 | ```jsx 41 | 42 | ``` 43 | 44 | ## 半星 45 | 46 | 设置 `allowHalf` 属性后可以选中半星。 47 | 48 | ```jsx 49 | 50 | ``` 51 | 52 | ## 自定义数量 53 | 54 | 通过 `count` 属性设置评分总数。 55 | 56 | ```jsx 57 | 58 | ``` 59 | 60 | ## 禁用状态 61 | 62 | 通过 `disabled` 属性来禁用评分。 63 | 64 | ```jsx 65 | 66 | ``` 67 | 68 | ## 只读状态显示小数 69 | 70 | 设置 `readonly` 和 `allowHalf` 属性后,Rate 组件可以展示任意小数结果。 71 | 72 | ```jsx 73 | 74 | ``` 75 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Rate/index.ts: -------------------------------------------------------------------------------- 1 | import Rate from './Rate'; 2 | 3 | export default Rate; 4 | export { Rate }; 5 | export type { RateProps } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Rate/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import type { ViewStyle } from 'react-native'; 3 | 4 | interface Styles { 5 | wrapper: ViewStyle; 6 | item: ViewStyle; 7 | half: ViewStyle; 8 | } 9 | 10 | export const createStyle = (): Styles => { 11 | return StyleSheet.create({ 12 | half: { 13 | left: 0, 14 | overflow: 'hidden', 15 | position: 'absolute', 16 | top: 0, 17 | }, 18 | 19 | item: { 20 | position: 'relative', 21 | }, 22 | 23 | wrapper: { 24 | alignItems: 'center', 25 | flexDirection: 'row', 26 | }, 27 | }); 28 | }; 29 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Rate/type.ts: -------------------------------------------------------------------------------- 1 | import type { StyleProp, ViewStyle } from 'react-native'; 2 | import type { IconNames } from '@pingtou/rn-vant-icons'; 3 | 4 | export interface RateProps { 5 | /** 6 | * 图标大小,默认单位为px 7 | * @default 20 8 | */ 9 | size?: number; 10 | /** 11 | * 选中时的颜色 12 | * @default 'f44336' 13 | */ 14 | color?: string; 15 | /** 16 | * 图标间距,默认单位为px 17 | * @default 4 18 | */ 19 | gutter?: number; 20 | /** 21 | * 是否为只读状态,只读状态下无法修改评分 22 | */ 23 | readonly?: boolean; 24 | /** 是否禁用评分 */ 25 | disabled?: boolean; 26 | /** 是否允许半选 */ 27 | allowHalf?: boolean; 28 | /** 未选中时的颜色 */ 29 | voidColor?: string; 30 | /** 31 | * 是否可以通过滑动手势选择评分 32 | * @default true 33 | */ 34 | touchable?: boolean; 35 | /** 禁用时的颜色 */ 36 | disabledColor?: string; 37 | /** 当前分值 */ 38 | value?: number; 39 | /** 默认分值 */ 40 | defaultValue?: number; 41 | /** 当前分值变化时触发的事件 */ 42 | onChange?: (v: number) => void; 43 | /** 44 | * 选中时的图标名称或图片链接 45 | * @default 'star' 46 | */ 47 | icon?: IconNames; 48 | /** 49 | * 未选中时的图标名称或图片链接 50 | * @default 'star-o' 51 | */ 52 | voidIcon?: IconNames; 53 | /** 54 | * 图标总数 55 | * @default 5 56 | */ 57 | count?: number; 58 | style?: StyleProp; 59 | } 60 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Search/index.ts: -------------------------------------------------------------------------------- 1 | import Search from './Search'; 2 | 3 | export default Search; 4 | export { Search }; 5 | export type { SearchProps, SearchInstance } from './types'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Search/types.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { FieldCommonProps } from '../Field/type'; 3 | 4 | export interface SearchProps extends FieldCommonProps { 5 | /** 搜索框左侧文本 */ 6 | label?: React.ReactNode; 7 | /** 取消按钮文字 */ 8 | actionText?: React.ReactNode; 9 | /** 搜索框外部背景色 */ 10 | background?: string; 11 | /** 是否在搜索框右侧显示取消按钮 */ 12 | showAction?: boolean; 13 | /** 搜索框形状,可选值为 round */ 14 | action?: React.ReactNode; 15 | shape?: 'square' | 'round'; 16 | /** 确定搜索时触发 */ 17 | onSearch?: (val: string) => void; 18 | /** 点击取消按钮时触发 */ 19 | onCancel?: () => void; 20 | } 21 | 22 | export type SearchInstance = { 23 | /** 获取输入框焦点 */ 24 | focus?: (e: React.MouseEvent) => void; 25 | /** 取消输入框焦点 */ 26 | blur?: (e: React.MouseEvent) => void; 27 | }; 28 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Selector/CheckMark.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import Svg, { SvgProps, G, Polyline } from 'react-native-svg'; 3 | 4 | export const CheckMark = memo((props: SvgProps) => ( 5 | 6 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | )); 26 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Selector/index.ts: -------------------------------------------------------------------------------- 1 | import Selector from './Selector'; 2 | 3 | export default Selector; 4 | export { Selector }; 5 | export type { SelectorValue, SelectorProps, SelectorOption } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Selector/type.ts: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | import type { StyleProp, ViewStyle } from 'react-native'; 3 | 4 | export type SelectorValue = string | number; 5 | 6 | export interface SelectorOption { 7 | // 文字 8 | label: ReactNode; 9 | // 描述 10 | description?: ReactNode; 11 | // 选项的值 12 | value: V; 13 | // 是否禁用 14 | disabled?: boolean; 15 | } 16 | 17 | export type SelectorProps = { 18 | // 可选项 19 | options: SelectorOption[]; 20 | // 行展示数 21 | columns?: number; 22 | // 是否允许多选 23 | multiple?: boolean; 24 | // 是否全局禁止选中 25 | disabled?: boolean; 26 | // 默认项 27 | defaultValue?: V[]; 28 | // 选中项 29 | value?: V[]; 30 | // 选项改变时触发 31 | onChange?: (v: V[], extend: { items: SelectorOption[] }) => void; 32 | // 是否显示对勾角标 33 | showCheckMark?: boolean; 34 | style?: StyleProp; 35 | }; 36 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Slider/index.tsx: -------------------------------------------------------------------------------- 1 | import Slider from './Slider'; 2 | 3 | export default Slider; 4 | export { Slider }; 5 | export type { SliderProps } from './types'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Space/index.ts: -------------------------------------------------------------------------------- 1 | import Space from './Space'; 2 | 3 | export { Space }; 4 | export default Space; 5 | export type { SpaceProps } from './type'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Space/style.ts: -------------------------------------------------------------------------------- 1 | import type { FlexAlignType, FlexStyle } from 'react-native'; 2 | import type { SpaceProps } from './type'; 3 | 4 | export const flexAlign: Record['align'], FlexAlignType> = { 5 | baseline: 'baseline', 6 | center: 'center', 7 | end: 'flex-end', 8 | start: 'flex-start', 9 | }; 10 | 11 | export const flexJustify: Record['justify'], FlexStyle['justifyContent']> = { 12 | around: 'space-around', 13 | between: 'space-between', 14 | center: 'center', 15 | end: 'flex-end', 16 | evenly: 'space-evenly', 17 | start: 'flex-start', 18 | stretch: undefined, 19 | }; 20 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Space/type.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { Pressable, StyleProp, ViewStyle } from 'react-native'; 3 | 4 | type PressableProps = React.ComponentProps; 5 | 6 | export interface SpaceProps extends PressableProps { 7 | /** 间距方向 8 | * @default horizontal 9 | */ 10 | direction?: 'horizontal' | 'vertical'; 11 | /** 交叉轴对齐方式 */ 12 | align?: 'start' | 'end' | 'center' | 'baseline'; 13 | /** 主轴对齐方式 */ 14 | justify?: 'start' | 'end' | 'center' | 'between' | 'around' | 'evenly' | 'stretch'; 15 | /** 是否自动换行,仅在 horizontal 时有效 */ 16 | wrap?: boolean; 17 | /** 18 | * 间距大小 19 | * 设为数组时则分别设置垂直方向和水平方向的间距大小 20 | * @default 8px 21 | */ 22 | gap?: number; 23 | style?: StyleProp; 24 | /** 分隔内容 */ 25 | divider?: React.ReactNode; 26 | } 27 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Stepper/index.ts: -------------------------------------------------------------------------------- 1 | import Stepper from './Stepper'; 2 | 3 | export { Stepper }; 4 | export type { StepperProps, StepperTheme } from './type'; 5 | -------------------------------------------------------------------------------- /packages/rn-vant/src/SwipeCell/index.ts: -------------------------------------------------------------------------------- 1 | import SwipeCell from './SwipeCell'; 2 | 3 | export { SwipeCell }; 4 | export type { SwipeCellInstance, SwipeCellProps, SwipeCellRenderAction } from './type'; 5 | -------------------------------------------------------------------------------- /packages/rn-vant/src/SwipeCell/type.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { StyleProp, ViewStyle } from 'react-native'; 3 | import type { SwipeableProps } from 'react-native-gesture-handler/Swipeable'; 4 | 5 | export type SwipeCellRenderAction = SwipeableProps['renderLeftActions']; 6 | 7 | export interface SwipeCellProps { 8 | style?: StyleProp; 9 | /** 标识符,可以在事件参数中获取到 */ 10 | name?: string | number; 11 | /** 左侧滑动区域的内容 */ 12 | leftAction?: React.ReactNode | SwipeCellRenderAction; 13 | /** 右侧滑动区域的内容 */ 14 | rightAction?: React.ReactNode | SwipeCellRenderAction; 15 | /** 是否禁用 */ 16 | disabled?: boolean; 17 | /** 打开时触发 */ 18 | onOpen?: ({ name, position }: { name: string | number; position: SwipeCellSide }) => void; 19 | /** 关闭时触发 */ 20 | onClose?: ({ name, position }: { name: string | number; position: SwipeCellSide }) => void; 21 | children?: React.ReactNode; 22 | } 23 | 24 | export type SwipeCellSide = 'left' | 'right'; 25 | 26 | export type SwipeCellInstance = { 27 | open: (side: SwipeCellSide) => void; 28 | close: () => void; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Swiper/SwiperItem.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef } from 'react'; 2 | import { View, Pressable } from 'react-native'; 3 | 4 | import type { SwiperItemProps } from './type'; 5 | 6 | const SwiperItem = forwardRef((props, ref) => { 7 | const { children, ...rest } = props; 8 | 9 | return ( 10 | 11 | {children} 12 | 13 | ); 14 | }); 15 | 16 | export default SwiperItem; 17 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Swiper/index.ts: -------------------------------------------------------------------------------- 1 | import InternalSwiper from './Swiper'; 2 | import SwiperItem from './SwiperItem'; 3 | 4 | export const Swiper = Object.assign(InternalSwiper, { Item: SwiperItem }); 5 | 6 | export default Swiper; 7 | export type { SwiperInstance, SwiperProps } from './type'; 8 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Swiper/type.ts: -------------------------------------------------------------------------------- 1 | import type { PressableProps, ViewProps } from 'react-native'; 2 | import type { ReactNode } from 'react'; 3 | 4 | export interface SwiperProps extends ViewProps { 5 | /** 滑块宽度 */ 6 | width?: number; 7 | /** 滑块高度 */ 8 | height?: number; 9 | /** 初始位置索引值 */ 10 | initialSwipe?: number; 11 | /** 是否允许手势滑动 */ 12 | touchable?: boolean; 13 | /** 自动轮播间隔,单位为 ms */ 14 | autoplay?: boolean | number; 15 | /** 是否开启循环播放 */ 16 | loop?: boolean; 17 | /** 是否为纵向滚动 */ 18 | vertical?: boolean; 19 | /** 每一页轮播结束后触发 */ 20 | onChange?: (index: number) => void; 21 | /** 自定义指示器 */ 22 | indicator?: boolean | ((total: number, current: number) => ReactNode); 23 | } 24 | 25 | export type SwiperItemProps = PressableProps; 26 | 27 | export type SwiperInstance = { 28 | activeIndex: number; 29 | swipeTo: (index: number) => void; 30 | swipeNext: () => void; 31 | swipePrev: () => void; 32 | }; 33 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Switch/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Switch 开关 3 | desc: 用于在打开和关闭状态之间进行切换。 4 | demo: /switch 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 基础组件 11 | --- 12 | 13 | ## 基础用法 14 | 15 | 通过 `defaultChecked` 默认开关的选中状态,`true` 表示开,`false` 表示关。 16 | 17 | ```jsx 18 | 19 | ``` 20 | 21 | ## 禁用状态 22 | 23 | 通过 `disabled` 属性来禁用开关,禁用状态下开关不可点击。 24 | 25 | ```jsx 26 | 27 | ``` 28 | 29 | ## 加载状态 30 | 31 | 通过 `loading` 属性设置开关为加载状态,加载状态下开关不可点击。 32 | 33 | ```jsx 34 | 35 | ``` 36 | 37 | ## 自定义大小 38 | 39 | 通过 `size` 属性自定义开关的大小。 40 | 41 | ```jsx 42 | 43 | ``` 44 | 45 | ## 自定义颜色 46 | 47 | `activeColor` 属性表示打开时的背景色,`inactiveColor` 表示关闭时的背景色。 48 | 49 | ```jsx 50 | 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Switch/index.ts: -------------------------------------------------------------------------------- 1 | import Switch from './Switch'; 2 | 3 | export default Switch; 4 | export { Switch }; 5 | export type { SwitchProps } from './interface'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Switch/interface.ts: -------------------------------------------------------------------------------- 1 | import type { ViewStyle, StyleProp } from 'react-native'; 2 | 3 | export interface SwitchProps { 4 | /** 5 | * 开关尺寸 6 | */ 7 | size?: number; 8 | /** 9 | * 是否为加载状态 10 | */ 11 | loading?: boolean; 12 | /** 13 | * 是否为禁用状态 14 | */ 15 | disabled?: boolean; 16 | /** 17 | * 开关选中状态 18 | */ 19 | checked?: boolean; 20 | /** 21 | * 开关默认选中状态 22 | */ 23 | defaultChecked?: boolean; 24 | /** 25 | * 打开时的背景色 26 | */ 27 | activeColor?: string; 28 | /** 29 | * 关闭时的背景色 30 | */ 31 | inactiveColor?: string; 32 | /** 33 | * 打开时对应的值 34 | * @default true 35 | */ 36 | activeValue?: any; 37 | /** 38 | * 关闭时对应的值 39 | * @default false 40 | */ 41 | inactiveValue?: any; 42 | /** 43 | * 开关状态切换时触发 44 | */ 45 | onChange?: (val: any) => void; 46 | onPress?: () => void; 47 | style?: StyleProp; 48 | } 49 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Tabs/TabPane.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef, useContext, useState, useMemo } from 'react'; 2 | import { View } from 'react-native'; 3 | import { TabsContext } from './TabsContext'; 4 | import type { TabPaneProps } from './type'; 5 | 6 | export const TabPane = forwardRef((props, ref) => { 7 | const { children, index, style } = props; 8 | const parent = useContext(TabsContext); 9 | const { animated, swipeable, lazyRender, lazyRenderPlaceholder } = parent.props; 10 | 11 | const active = parent.selectedIndex === index; 12 | 13 | const [inited, setInited] = useState(() => active); 14 | 15 | const isActive = useMemo(() => { 16 | if (active && !inited) { 17 | setInited(true); 18 | } 19 | return active; 20 | }, [active, inited]); 21 | 22 | const show = isActive; 23 | const shouldRender = inited || !lazyRender; 24 | const Content = shouldRender ? children : lazyRenderPlaceholder; 25 | 26 | if (animated || swipeable) { 27 | return {Content}; 28 | } 29 | 30 | return ( 31 | 32 | {Content} 33 | 34 | ); 35 | }); 36 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Tabs/TabsContext.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | import type { TabsProps } from './type'; 3 | 4 | export interface TabsContextState { 5 | props: React.PropsWithChildren; 6 | selectedIndex: number; 7 | setCurrentIndex: (index: number) => void; 8 | } 9 | 10 | export const TabsContext = createContext({} as TabsContextState); 11 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Tabs/index.ts: -------------------------------------------------------------------------------- 1 | import { TabPane } from './TabPane'; 2 | import TabInner from './Tabs'; 3 | 4 | export const Tabs = Object.assign(TabInner, { TabPane }); 5 | 6 | export * from './type'; 7 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Tabs/utils.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export function parseChildList } & T>( 4 | children: React.ReactNode 5 | ): R[] { 6 | return React.Children.toArray(children).reduce((result, node) => { 7 | if (React.isValidElement(node)) { 8 | const key = node.key !== undefined ? String(node.key) : undefined; 9 | result.push({ 10 | key, 11 | ...node.props, 12 | node, 13 | }); 14 | } 15 | return result; 16 | }, []); 17 | } 18 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Tag/index.tsx: -------------------------------------------------------------------------------- 1 | import Tag from './Tag'; 2 | 3 | export default Tag; 4 | export { Tag }; 5 | export type { TagProps } from './interface'; 6 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Theme/index.tsx: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react'; 2 | import { createTheming } from '@callstack/react-theme-provider'; 3 | import type { StyleSheet } from 'react-native'; 4 | import { defaultTheme } from '../styles'; 5 | 6 | export const { ThemeProvider, withTheme, useTheme } = createTheming( 7 | defaultTheme as DiceUI.Theme 8 | ); 9 | 10 | type ThemeFactoryCallBack> = { 11 | styles: T; 12 | theme: DiceUI.Theme; 13 | }; 14 | 15 | export function useThemeFactory, P>( 16 | fun: (theme: DiceUI.Theme, ...extra: P[]) => T, 17 | ...params: P[] 18 | ): ThemeFactoryCallBack { 19 | const theme = useTheme(); 20 | const styles = useMemo(() => fun(theme, ...params), [fun, theme, params]); 21 | 22 | return { styles, theme }; 23 | } 24 | 25 | export default { 26 | ThemeProvider, 27 | withTheme, 28 | useTheme, 29 | useThemeFactory, 30 | }; 31 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Toast/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Toast 轻提示 3 | desc: 在页面中间弹出黑色半透明提示,用于消息通知、加载提示、操作结果提示等场景。 4 | demo: /toast 5 | 6 | nav: 7 | path: / 8 | 9 | group: 10 | title: 基础组件 11 | --- 12 | 13 | ## 引入 14 | 15 | ```jsx 16 | import { Toast } from '@pingtou/rn-vant'; 17 | ``` 18 | 19 | ## 文字提示 20 | 21 | ```jsx 22 | Toast.message('提示内容') 23 | ``` 24 | 25 | ## 加载提示 26 | 27 | 使用 `Toast.loading` 方法展示加载提示。 28 | 29 | ```jsx 30 | Toast.loading('加载中...') 31 | ``` 32 | 33 | ## 成功/失败提示 34 | 35 | 使用 `Toast.success` 方法展示成功提示,使用 `Toast.fail` 方法展示失败提示。 36 | 37 | ```jsx 38 | Toast.success('成功文案'); 39 | Toast.fail('失败文案'); 40 | ``` 41 | 42 | ## 自定义图标 43 | 44 | 通过 `icon` 选项可以自定义图标,支持传入图标名称,通过loadingType 属性可以自定义加载图标类型。 45 | 46 | ```jsx 47 | Toast.show({ 48 | text: '自定义图标', 49 | icon: 'like-o', 50 | }) 51 | 52 | Toast.loading({ 53 | text: '加载中...', 54 | loadingType: 'spinner', 55 | }) 56 | ``` 57 | 58 | ## 自定义位置 59 | 60 | Toast 默认渲染在屏幕正中位置,通过 `position` 属性可以控制 Toast 展示的位置。 61 | 62 | ```jsx 63 | Toast.message({ 64 | text: '提示内容', 65 | position: 'top', 66 | }) 67 | 68 | Toast.message({ 69 | text: '提示内容', 70 | position: 'bottom', 71 | }) 72 | ``` 73 | -------------------------------------------------------------------------------- /packages/rn-vant/src/TouchableOpacity/type.ts: -------------------------------------------------------------------------------- 1 | import type { PressableProps, ViewProps } from 'react-native'; 2 | 3 | export interface TouchableOpacityProps extends Omit { 4 | style?: ViewProps['style']; 5 | // 背景颜色 6 | backgroundColor?: string; 7 | // onPress 回调的节流时间,单位 ms 8 | throttleTime?: number; 9 | // 节流函数的参数 10 | throttleOptions?: { leading: boolean; trailing: boolean }; 11 | // 按下时的背景颜色 12 | activeBackgroundColor?: string; 13 | // 按下时背景透明度 14 | activeOpacity?: number; 15 | } 16 | -------------------------------------------------------------------------------- /packages/rn-vant/src/TouchableRipple/index.ts: -------------------------------------------------------------------------------- 1 | import TouchableRipple from './TouchableRipple'; 2 | 3 | export default TouchableRipple; 4 | export { TouchableRipple }; 5 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Transitions/Fade.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo, forwardRef } from 'react'; 2 | 3 | import Transition from './Transition'; 4 | import type { FadeProps } from './types'; 5 | 6 | const Fade = forwardRef((props, ref) => { 7 | const { children, in: animationState, entryDuration, exitDuration, ...rest } = props; 8 | 9 | return ( 10 | 18 | {children} 19 | 20 | ); 21 | }); 22 | 23 | Fade.defaultProps = { 24 | entryDuration: 500, 25 | exitDuration: 500, 26 | }; 27 | Fade.displayName = 'Transitions.Fade'; 28 | 29 | export default memo(Fade); 30 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Transitions/ScaleFade.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo, forwardRef } from 'react'; 2 | 3 | import type { ScaleFadeProps } from './types'; 4 | import Transition from './Transition'; 5 | 6 | const ScaleFade = forwardRef((props, ref) => { 7 | const { children, initialScale, duration, in: animationState, ...rest } = props; 8 | 9 | return ( 10 | 18 | {children} 19 | 20 | ); 21 | }); 22 | 23 | ScaleFade.defaultProps = { 24 | duration: 500, 25 | initialScale: 0.9, 26 | }; 27 | ScaleFade.displayName = 'Transitions.ScaleFade'; 28 | 29 | export default memo(ScaleFade); 30 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Transitions/index.ts: -------------------------------------------------------------------------------- 1 | import Fade from './Fade'; 2 | import ScaleFade from './ScaleFade'; 3 | import Transition from './Transition'; 4 | import SlideFade from './SlideFade'; 5 | import Stagger from './Stagger'; 6 | import Slide from './Slide'; 7 | 8 | export const Transitions = { 9 | Fade, 10 | ScaleFade, 11 | Transition, 12 | SlideFade, 13 | Stagger, 14 | Slide, 15 | }; 16 | 17 | export default Transitions; 18 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Typography/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { TypographyTextProps, TypographyTitleProps, TypographyLinkProps } from './type'; 3 | import Typography from './Typography'; 4 | 5 | const Text = (props: TypographyTextProps) => ; 6 | const Title = (props: TypographyTitleProps) => ; 7 | const Link = (props: TypographyLinkProps) => ; 8 | 9 | const TypographyNamespace = Object.assign(Typography, { Text, Title, Link }); 10 | 11 | export default TypographyNamespace; 12 | export { TypographyNamespace as Typography }; 13 | export type { 14 | TypographyBaseProps as TypographyProps, 15 | TypographySize, 16 | TypographyType, 17 | TypographyTitleLevel, 18 | } from './type'; 19 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Typography/type.ts: -------------------------------------------------------------------------------- 1 | import type { TextProps } from 'react-native'; 2 | 3 | export type TypographyType = 'danger' | 'secondary' | 'light' | 'primary' | 'success' | 'warning'; 4 | export type TypographySize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; 5 | export type TypographyTitleLevel = 1 | 2 | 3 | 4 | 5; 6 | 7 | export interface TypographyBaseProps extends TextProps { 8 | type?: TypographyType; 9 | size?: TypographySize; 10 | level?: TypographyTitleLevel; 11 | disabled?: boolean; 12 | delete?: boolean; 13 | underline?: boolean; 14 | center?: boolean; 15 | strong?: boolean; 16 | ellipsis?: boolean | number; 17 | onPress?: () => void; 18 | } 19 | 20 | export type TypographyTextProps = Omit; 21 | export type TypographyTitleProps = TypographyBaseProps; 22 | export type TypographyLinkProps = Omit; 23 | -------------------------------------------------------------------------------- /packages/rn-vant/src/Uploader/type.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bijinfeng/rn-vant/a465ecb3f06dbdaf084b98455c6812b93f16fc43/packages/rn-vant/src/Uploader/type.ts -------------------------------------------------------------------------------- /packages/rn-vant/src/View/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Animated, View as RNView, SafeAreaView } from 'react-native'; 3 | import type { ViewProps } from './type'; 4 | 5 | const View = React.forwardRef((props: ViewProps, ref) => { 6 | const { children, useSafeArea, animated, style, ...rest } = props; 7 | 8 | const Element = useSafeArea ? SafeAreaView : RNView; 9 | const Container: React.ClassType = animated 10 | ? Animated.createAnimatedComponent(Element) 11 | : Element; 12 | 13 | return ( 14 | 15 | {children} 16 | 17 | ); 18 | }); 19 | 20 | export default View; 21 | -------------------------------------------------------------------------------- /packages/rn-vant/src/View/type.ts: -------------------------------------------------------------------------------- 1 | import type { ViewProps as RNViewProps, StyleProp, ViewStyle, Animated } from 'react-native'; 2 | 3 | export interface ViewProps extends Omit { 4 | /** 5 | * 是否开启安全区适配, 为 true 时使用 SafeAreaView 6 | */ 7 | useSafeArea?: boolean; 8 | /** 9 | * 是否使用 Animate.View 10 | */ 11 | animated?: boolean; 12 | style?: StyleProp>; 13 | } 14 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { default as useMemoizedFn } from './useMemoizedFn'; 2 | export { default as useControllableValue } from './useControllableValue'; 3 | export { default as useUpdateEffect } from './useUpdateEffect'; 4 | export { default as useSetState } from './useSetState'; 5 | export { default as useUpdate } from './useUpdate'; 6 | export { default as useOrientation } from './useOrientation'; 7 | export { default as useScrollTo } from './useScrollTo'; 8 | export { default as useRefState } from './useRefState'; 9 | export { default as useRefs } from './useRefs'; 10 | export { default as useLazyRender } from './useLazyRender'; 11 | export { default as useLazyRef } from './useLazyRef'; 12 | export { default as useAnimatedValue } from './useAnimatedValue'; 13 | export { default as useAnimatedValueArray } from './useAnimatedValueArray'; 14 | export { default as useLayout } from './useLayout'; 15 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useAnimatedValue.ts: -------------------------------------------------------------------------------- 1 | import { Animated } from 'react-native'; 2 | import useLazyRef from './useLazyRef'; 3 | 4 | const useAnimatedValue = (initialValue: number): Animated.Value => { 5 | const { current } = useLazyRef(() => new Animated.Value(initialValue)); 6 | 7 | return current; 8 | }; 9 | export default useAnimatedValue; 10 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useAnimatedValueArray.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Animated } from 'react-native'; 3 | 4 | export default function useAnimatedValueArray(initialValues: number[]): Animated.Value[] { 5 | const refs = React.useRef([]); 6 | 7 | refs.current.length = initialValues.length; 8 | initialValues.forEach((initialValue, i) => { 9 | refs.current[i] = refs.current[i] ?? new Animated.Value(initialValue); 10 | }); 11 | 12 | return refs.current; 13 | } 14 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useDestroyed.ts: -------------------------------------------------------------------------------- 1 | import { useRef, useCallback, useEffect } from 'react'; 2 | 3 | /** 4 | * 组件是否已经被销毁了 5 | */ 6 | const useDestroyed = () => { 7 | const DestroyedRef = useRef(true); 8 | const getDestroyed = useCallback(() => DestroyedRef.current, []); 9 | 10 | useEffect(() => { 11 | DestroyedRef.current = false; 12 | 13 | return () => { 14 | DestroyedRef.current = true; 15 | }; 16 | }, []); 17 | 18 | return getDestroyed; 19 | }; 20 | 21 | export default useDestroyed; 22 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useLayout.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import type { LayoutChangeEvent } from 'react-native'; 3 | 4 | export default function useLayout() { 5 | const [layout, setLayout] = React.useState<{ 6 | height: number; 7 | width: number; 8 | measured: boolean; 9 | }>({ height: 0, width: 0, measured: false }); 10 | 11 | const onLayout = React.useCallback( 12 | (e: LayoutChangeEvent) => { 13 | const { height, width } = e.nativeEvent.layout; 14 | 15 | if (height === layout.height && width === layout.width) { 16 | return; 17 | } 18 | 19 | setLayout({ 20 | height, 21 | width, 22 | measured: true, 23 | }); 24 | }, 25 | [layout.height, layout.width] 26 | ); 27 | 28 | return [layout, onLayout] as const; 29 | } 30 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useLazyRef.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export default function useLazyRef(callback: () => T): React.MutableRefObject { 4 | const lazyRef = React.useRef(); 5 | 6 | if (lazyRef.current === undefined) { 7 | lazyRef.current = callback(); 8 | } 9 | 10 | return lazyRef as React.MutableRefObject; 11 | } 12 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useLazyRender.ts: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, ReactNode } from 'react'; 2 | 3 | function useLazyRender(show: boolean): (render: () => React.ReactNode) => () => ReactNode { 4 | const [inited, setInited] = useState(false); 5 | 6 | useEffect(() => { 7 | if (show) { 8 | setInited(show); 9 | } 10 | }, [show]); 11 | 12 | return render => () => inited ? render() : null; 13 | } 14 | 15 | export default useLazyRender; 16 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useMemoizedFn.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 代码来源:https://github.com/alibaba/hooks/blob/master/packages/hooks/src/useMemoizedFn/index.ts 3 | * 关于 this:https://www.jianshu.com/p/8b3a2513d8e5 4 | */ 5 | 6 | import { useMemo, useRef } from 'react'; 7 | 8 | type noop = (...args: any[]) => any; 9 | 10 | /** 11 | * 持久化 function 的 hook 12 | */ 13 | function useMemoizedFn(fn: T) { 14 | if (process.env.NODE_ENV === 'development') { 15 | if (typeof fn !== 'function') { 16 | console.error(`useMemoizedFn expected parameter is a function, got ${typeof fn}`); 17 | } 18 | } 19 | 20 | const fnRef = useRef(fn); 21 | 22 | // why not write `fnRef.current = fn`? 23 | // https://github.com/alibaba/hooks/issues/728 24 | fnRef.current = useMemo(() => fn, [fn]); 25 | 26 | const memoizedFn = useRef(); 27 | if (!memoizedFn.current) { 28 | memoizedFn.current = function (this: T, ...args) { 29 | return fnRef.current.apply(this, args); 30 | } as T; 31 | } 32 | 33 | return memoizedFn.current; 34 | } 35 | 36 | export default useMemoizedFn; 37 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useOrientation.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useCallback, useState } from 'react'; 2 | import constants, { orientations } from '../utils/constants'; 3 | import useUpdateEffect from './useUpdateEffect'; 4 | 5 | interface UseOrientationProps { 6 | onOrientationChange?: (orientation: orientations) => void; 7 | } 8 | 9 | type UseOrientation = ({ onOrientationChange }: UseOrientationProps) => { 10 | orientation: orientations; 11 | }; 12 | 13 | /** 14 | * 监听屏幕方向变动的 hook 15 | */ 16 | const useOrientation: UseOrientation = ({ onOrientationChange }) => { 17 | const [orientation, setOrientation] = useState(constants.orientation); 18 | 19 | const orientationChangeListener = useCallback(() => { 20 | setOrientation(constants.orientation); 21 | }, []); 22 | 23 | useEffect(() => { 24 | const listener = constants.addDimensionsEventListener(orientationChangeListener); 25 | return () => constants.removeDimensionsEventListener(listener); 26 | }, []); 27 | 28 | useUpdateEffect(() => { 29 | onOrientationChange?.(orientation); 30 | }, [orientation]); 31 | 32 | return { orientation }; 33 | }; 34 | 35 | export default useOrientation; 36 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useRefState.ts: -------------------------------------------------------------------------------- 1 | import { useCallback, useRef, useState } from 'react'; 2 | import type { Dispatch, SetStateAction, MutableRefObject } from 'react'; 3 | import isFunction from 'lodash-es/isFunction'; 4 | 5 | type StateType = T | (() => T); 6 | 7 | export default function useRefState( 8 | initialState: StateType 9 | ): [T, Dispatch>, MutableRefObject] { 10 | const [state, setState] = useState(initialState); 11 | const ref = useRef(state); 12 | const setRafState = useCallback( 13 | patch => { 14 | setState(prevState => { 15 | // eslint-disable-next-line no-return-assign 16 | return (ref.current = isFunction(patch) ? patch(prevState) : patch); 17 | }); 18 | }, 19 | [state] 20 | ); 21 | return [state, setRafState, ref]; 22 | } 23 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useRefs.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { View } from 'react-native'; 3 | 4 | export default function useRefs(): [T[], (index: number) => (el: T) => void, () => void] { 5 | const refs = React.useRef([]); 6 | 7 | const setRefs = React.useCallback( 8 | (index: number) => (el: T) => { 9 | if (el) refs.current[index] = el; 10 | }, 11 | [] 12 | ); 13 | 14 | const reset = React.useCallback(() => { 15 | refs.current = []; 16 | }, []); 17 | 18 | return [refs.current, setRefs, reset]; 19 | } 20 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useSetState.ts: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import isFunction from 'lodash-es/isFunction'; 3 | import useRefState from './useRefState'; 4 | import useUnmountedRef from './useUnmountedRef'; 5 | 6 | // eslint-disable-next-line @typescript-eslint/ban-types 7 | const useSetState = ( 8 | initialState: T = {} as T 9 | ): [T, (patch: Partial | ((prevState: T) => Partial)) => void, React.MutableRefObject] => { 10 | const unmountedRef = useUnmountedRef(); 11 | const [state, setState, ref] = useRefState(initialState); 12 | 13 | const setMergeState = useCallback(patch => { 14 | if (unmountedRef.current) return; 15 | setState(prevState => ({ ...prevState, ...(isFunction(patch) ? patch(prevState) : patch) })); 16 | }, []); 17 | 18 | return [state, setMergeState, ref]; 19 | }; 20 | 21 | export default useSetState; 22 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useUnmountedRef.ts: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect } from 'react'; 2 | 3 | const useUnmountedRef = (): React.MutableRefObject => { 4 | const unmountedRef = useRef(false); 5 | useEffect(() => { 6 | unmountedRef.current = false; 7 | 8 | return () => { 9 | unmountedRef.current = true; 10 | }; 11 | }, []); 12 | return unmountedRef; 13 | }; 14 | 15 | export default useUnmountedRef; 16 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useUpdate.ts: -------------------------------------------------------------------------------- 1 | import { useCallback, useState } from 'react'; 2 | 3 | const useUpdate = () => { 4 | const [, setState] = useState({}); 5 | 6 | return useCallback(() => setState({}), []); 7 | }; 8 | 9 | export default useUpdate; 10 | -------------------------------------------------------------------------------- /packages/rn-vant/src/hooks/useUpdateEffect.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { createUpdateEffect } from '../utils/createUpdateEffect'; 3 | 4 | export default createUpdateEffect(useEffect); 5 | -------------------------------------------------------------------------------- /packages/rn-vant/src/locale/index.ts: -------------------------------------------------------------------------------- 1 | export { default as zhCN, mergeLocale } from './lang/zh-CN'; 2 | export type { PartialLocale } from './lang/zh-CN'; 3 | export { default as zhHK } from './lang/zh-HK'; 4 | export { default as zhTW } from './lang/zh-TW'; 5 | export { default as enUS } from './lang/en-US'; 6 | export { default as jaJP } from './lang/ja-JP'; 7 | export { default as frFR } from './lang/fr-FR'; 8 | -------------------------------------------------------------------------------- /packages/rn-vant/src/locale/lang/zh-CN.ts: -------------------------------------------------------------------------------- 1 | import { deepAssign } from '../../utils/deepAssign'; 2 | import { base } from './base'; 3 | import type { Locale } from './types'; 4 | 5 | type DeepPartial = { 6 | [P in keyof T]?: DeepPartial; 7 | }; 8 | 9 | export type PartialLocale = DeepPartial; 10 | 11 | const zhCN = deepAssign(base, {}); 12 | 13 | const mergeLocale = (baseLocal: Locale, mergeLocal: PartialLocale): Locale => { 14 | return deepAssign(baseLocal, mergeLocal) as Locale; 15 | }; 16 | 17 | export { mergeLocale }; 18 | 19 | export default zhCN; 20 | -------------------------------------------------------------------------------- /packages/rn-vant/src/styles/darkTheme.ts: -------------------------------------------------------------------------------- 1 | import * as _vars from './variables'; 2 | import { createDefaultTheme } from './defaultTheme'; 3 | import { numberKeyBoardDarkVars } from '../NumberKeyboard/style'; 4 | 5 | const darkVars = { 6 | ..._vars, 7 | text_color: '#f5f5f5', 8 | text_color_2: '#707070', 9 | text_color_3: '#4d4d4d', 10 | border_color: '#3a3a3c', 11 | active_color: '#3a3a3c', 12 | background: '#000', 13 | background_2: '#1c1c1e', 14 | background_3: '#37363b', 15 | }; 16 | 17 | const createDarkTheme = (vars: typeof _vars) => ({ 18 | ...createDefaultTheme(vars), 19 | ...vars, 20 | dark: false, 21 | 22 | // Button 23 | button_plain_background_color: 'transparent', 24 | 25 | // Calendar 26 | calendar_month_mark_color: 'rgba(100, 101, 102, 0.2)', 27 | calendar_day_disabled_color: vars.gray_7, 28 | 29 | // Picker 30 | picker_mask_top_color: ['rgba(0, 0, 0, 0.6)', 'rgba(0, 0, 0, 0.1)'], 31 | picker_mask_bottom_color: ['rgba(0, 0, 0, 0.1)', 'rgba(0, 0, 0, 0.6)'], 32 | 33 | // NumberKeyboard 34 | ...numberKeyBoardDarkVars(vars), 35 | }); 36 | 37 | export const darkTheme = createDarkTheme(darkVars as typeof _vars); 38 | -------------------------------------------------------------------------------- /packages/rn-vant/src/styles/index.ts: -------------------------------------------------------------------------------- 1 | import type * as _vars from './variables'; 2 | import type { defaultTheme } from './defaultTheme'; 3 | 4 | export type Vars = typeof _vars; 5 | 6 | /** 默认变量类型 */ 7 | export type ThemeVarType = typeof defaultTheme; 8 | 9 | export { defaultTheme } from './defaultTheme'; 10 | export { darkTheme } from './darkTheme'; 11 | export * from './shortHand'; 12 | -------------------------------------------------------------------------------- /packages/rn-vant/src/tests/shared/snapshotTest.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import renderer from 'react-test-renderer'; 3 | 4 | const snapshotTest = (name: string, Component: React.ComponentType) => { 5 | it(name, () => { 6 | const component = renderer.create(); 7 | 8 | expect(component.toJSON()).toMatchSnapshot(); 9 | }); 10 | }; 11 | 12 | export default snapshotTest; 13 | -------------------------------------------------------------------------------- /packages/rn-vant/src/types.ts: -------------------------------------------------------------------------------- 1 | import type { PressableProps } from 'react-native'; 2 | import type { ThemeVarType } from './styles'; 3 | 4 | export type $Omit = Pick>; 5 | export type $RemoveChildren> = $Omit< 6 | React.ComponentPropsWithoutRef, 7 | 'children' 8 | >; 9 | 10 | export type EllipsizeProp = 'head' | 'middle' | 'tail' | 'clip'; 11 | 12 | declare global { 13 | // eslint-disable-next-line @typescript-eslint/no-namespace 14 | namespace DiceUI { 15 | type Theme = ThemeVarType; 16 | } 17 | } 18 | 19 | type Inline = Partial< 20 | { 21 | /** 22 | * @default None 23 | * @type PressableProps except click handlers 24 | */ 25 | pressableProps: Omit; 26 | } & Pick 27 | >; 28 | 29 | export type InlinePressableProps = Inline< 30 | PressableProps, 31 | 'onPress' | 'onLongPress' | 'onPressIn' | 'onPressOut' 32 | >; 33 | -------------------------------------------------------------------------------- /packages/rn-vant/src/utils/cloneReactNode.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const cloneReactNode = ( 4 | node: React.ReactNode, 5 | props?: Record 6 | ): React.ReactNode => { 7 | if (React.isValidElement(node) && props) { 8 | return React.cloneElement>(node, props); 9 | } 10 | 11 | return node; 12 | }; 13 | -------------------------------------------------------------------------------- /packages/rn-vant/src/utils/createUpdateEffect.ts: -------------------------------------------------------------------------------- 1 | import { useRef } from 'react'; 2 | import type { useEffect, useLayoutEffect } from 'react'; 3 | 4 | type effectHookType = typeof useEffect | typeof useLayoutEffect; 5 | 6 | export const createUpdateEffect: (hook: effectHookType) => effectHookType = 7 | hook => (effect, deps) => { 8 | const isMounted = useRef(false); 9 | 10 | // for react-refresh 11 | hook(() => { 12 | return () => { 13 | isMounted.current = false; 14 | }; 15 | }, []); 16 | 17 | // eslint-disable-next-line consistent-return 18 | hook(() => { 19 | if (!isMounted.current) { 20 | isMounted.current = true; 21 | } else { 22 | return effect(); 23 | } 24 | }, deps); 25 | }; 26 | -------------------------------------------------------------------------------- /packages/rn-vant/src/utils/deepAssign.ts: -------------------------------------------------------------------------------- 1 | import isObject from 'lodash-es/isObject'; 2 | import isNil from 'lodash-es/isNil'; 3 | 4 | type ObjectIndex = Record; 5 | 6 | function assignKey(to: ObjectIndex, from: ObjectIndex, key: string) { 7 | const val = from[key]; 8 | 9 | if (isNil(val)) { 10 | return; 11 | } 12 | 13 | if (!Object.prototype.hasOwnProperty.call(to, key) || !isObject(val)) { 14 | // eslint-disable-next-line no-param-reassign 15 | to[key] = val; 16 | } else { 17 | // eslint-disable-next-line 18 | to[key] = deepAssign(Object(to[key]), from[key]); 19 | } 20 | } 21 | 22 | export function deepAssign(to: ObjectIndex, from: ObjectIndex): ObjectIndex { 23 | Object.keys(from).forEach(key => { 24 | assignKey(to, from, key); 25 | }); 26 | 27 | return to; 28 | } 29 | -------------------------------------------------------------------------------- /packages/rn-vant/src/utils/devLog.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { isDev } from './isDev'; 3 | 4 | export function devWarning(component: string, message: string): void { 5 | if (isDev) { 6 | console.warn(`[rn-vant: ${component}] ${message}`); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/rn-vant/src/utils/getContrastingColor.ts: -------------------------------------------------------------------------------- 1 | import type { ColorValue } from 'react-native'; 2 | import color from 'color'; 3 | 4 | const getContrastingColor = (input: ColorValue, light: string, dark: string): string => { 5 | if (typeof input === 'string') { 6 | return color(input).isLight() ? dark : light; 7 | } 8 | 9 | return light; 10 | }; 11 | 12 | export default getContrastingColor; 13 | -------------------------------------------------------------------------------- /packages/rn-vant/src/utils/getShortHand.ts: -------------------------------------------------------------------------------- 1 | const getShortHand = (style: 'padding' | 'margin', ...values: any[]) => { 2 | if (values.length === 1) { 3 | return { [style]: values[0] }; 4 | } 5 | const _genCss = (...list: number[]) => ({ 6 | [style + 'Top']: list[0], 7 | [style + 'Right']: list[1], 8 | [style + 'Bottom']: list[2], 9 | [style + 'Left']: list[3], 10 | }); 11 | if (values.length === 2) { 12 | return _genCss(values[0], values[1], values[0], values[1]); 13 | } 14 | if (values.length === 3) { 15 | return _genCss(values[0], values[1], values[2], values[1]); 16 | } 17 | return _genCss(values[0], values[1], values[2], values[3]); 18 | }; 19 | 20 | /** 21 | * 简写 padding 和 margin 22 | */ 23 | export const padding = (...values: Array) => getShortHand('padding', ...values); 24 | export const margin = (...values: Array) => getShortHand('margin', ...values); 25 | -------------------------------------------------------------------------------- /packages/rn-vant/src/utils/isDev.ts: -------------------------------------------------------------------------------- 1 | export const isDev = process.env.NODE_ENV === 'development'; 2 | -------------------------------------------------------------------------------- /packages/rn-vant/src/utils/isIcon.ts: -------------------------------------------------------------------------------- 1 | import type { IconNames } from '@pingtou/rn-vant-icons'; 2 | import isString from 'lodash-es/isString'; 3 | 4 | export const isIcon = (icon: IconNames | React.ReactNode): icon is IconNames => isString(icon); 5 | -------------------------------------------------------------------------------- /packages/rn-vant/src/utils/isString.ts: -------------------------------------------------------------------------------- 1 | const { toString } = Object.prototype; 2 | 3 | /** 4 | * Gets the `toStringTag` of `value`. 5 | * 6 | * @private 7 | * @param {*} value The value to query. 8 | * @returns {string} Returns the `toStringTag`. 9 | */ 10 | function getTag(value: any) { 11 | if (value == null) { 12 | return value === undefined ? '[object Undefined]' : '[object Null]'; 13 | } 14 | return toString.call(value); 15 | } 16 | 17 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types 18 | const isString = (value: any): value is string => { 19 | const type = typeof value; 20 | return ( 21 | type === 'string' || 22 | (type === 'object' && 23 | value != null && 24 | !Array.isArray(value) && 25 | getTag(value) === '[object String]') 26 | ); 27 | }; 28 | 29 | export default isString; 30 | -------------------------------------------------------------------------------- /packages/rn-vant/src/utils/validate.ts: -------------------------------------------------------------------------------- 1 | export function isNumeric(val: string): boolean { 2 | return /^\d+(\.\d+)?$/.test(val); 3 | } 4 | 5 | export function isNaN(val: number): val is typeof NaN { 6 | if (Number.isNaN) { 7 | return Number.isNaN(val); 8 | } 9 | 10 | // eslint-disable-next-line no-self-compare 11 | return val !== val; 12 | } 13 | -------------------------------------------------------------------------------- /packages/rn-vant/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "exclude": ["example"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/rn-vant/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "paths": { 5 | "@pingtou/rn-vant": ["./src/index"], 6 | }, 7 | }, 8 | "exclude": ["lib/**/*"] 9 | } 10 | -------------------------------------------------------------------------------- /scripts/bootstrap.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | // eslint-disable-next-line camelcase 3 | const child_process = require('child_process'); 4 | 5 | const root = path.resolve(__dirname, '..'); 6 | const args = process.argv.slice(2); 7 | const options = { 8 | cwd: process.cwd(), 9 | env: process.env, 10 | stdio: 'inherit', 11 | encoding: 'utf-8', 12 | }; 13 | 14 | let result; 15 | 16 | if (process.cwd() !== root || args.length) { 17 | result = child_process.spawnSync('yarn', args, options); 18 | } else { 19 | result = child_process.spawnSync('yarn', ['bootstrap'], options); 20 | } 21 | 22 | process.exitCode = result.status; 23 | -------------------------------------------------------------------------------- /scripts/verify-commit-msg.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const msgPath = process.env.HUSKY_GIT_PARAMS; 3 | const msg = require('fs').readFileSync(msgPath, 'utf-8').trim(); 4 | 5 | const commitRE = 6 | /^(revert: )?(feat|fix|polish|docs|style|refactor|perf|test|workflow|ci|chore|types|build)(\(.+\))?: .{1,50}/; 7 | 8 | if (!commitRE.test(msg)) { 9 | console.log(); 10 | console.error( 11 | ` ${chalk.bgRed.white(' ERROR ')} ${chalk.red(`invalid commit message format.`)}\n\n` + 12 | chalk.red( 13 | ` Proper commit message format is required for automated changelog generation. Examples:\n\n` 14 | ) + 15 | ` ${chalk.green(`feat(compiler): add 'comments' option`)}\n` + 16 | ` ${chalk.green(`fix(v-model): handle events on blur (close #28)`)}\n\n` + 17 | chalk.red(` See .gitlab/COMMIT_CONVENTION.md for more details.\n`) + 18 | chalk.red( 19 | ` You can also use ${chalk.cyan(`git cz`)} to interactively generate a commit message.\n` 20 | ) 21 | ); 22 | process.exit(1); 23 | } 24 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "allowUnreachableCode": false, 5 | "allowUnusedLabels": false, 6 | "esModuleInterop": true, 7 | "importsNotUsedAsValues": "error", 8 | "forceConsistentCasingInFileNames": true, 9 | "jsx": "react", 10 | "lib": ["esnext", "dom"], 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "noFallthroughCasesInSwitch": true, 14 | "noImplicitReturns": true, 15 | "noImplicitUseStrict": false, 16 | "noStrictGenericChecks": false, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "resolveJsonModule": true, 20 | "skipLibCheck": true, 21 | "strict": true, 22 | "target": "esnext" 23 | }, 24 | } --------------------------------------------------------------------------------