├── packages └── nutui │ ├── components │ ├── collapse │ │ ├── index.scss │ │ ├── index.ts │ │ └── collapse.ts │ ├── swipegroup │ │ ├── index.scss │ │ ├── index.ts │ │ ├── swipegroup.ts │ │ └── swipegroup.vue │ ├── checkboxgroup │ │ ├── index.scss │ │ ├── index.ts │ │ └── checkboxgroup.ts │ ├── configprovider │ │ ├── index.scss │ │ ├── index.ts │ │ └── configprovider.ts │ ├── badge │ │ ├── index.ts │ │ └── badge.ts │ ├── card │ │ ├── index.ts │ │ └── card.ts │ ├── col │ │ ├── index.ts │ │ ├── col.ts │ │ ├── index.scss │ │ └── col.vue │ ├── grid │ │ ├── index.ts │ │ ├── index.scss │ │ ├── grid.ts │ │ └── grid.vue │ ├── menu │ │ ├── index.ts │ │ └── menu.ts │ ├── price │ │ ├── index.ts │ │ └── price.ts │ ├── radio │ │ ├── index.ts │ │ └── radio.ts │ ├── range │ │ ├── index.ts │ │ └── range.ts │ ├── rate │ │ ├── index.ts │ │ ├── index.scss │ │ └── rate.ts │ ├── row │ │ ├── index.ts │ │ ├── row.ts │ │ ├── row.vue │ │ └── index.scss │ ├── tabs │ │ ├── index.ts │ │ └── type.ts │ ├── tour │ │ └── index.ts │ ├── animate │ │ ├── index.ts │ │ ├── type.ts │ │ └── animate.ts │ ├── avatar │ │ ├── index.ts │ │ ├── avatar.ts │ │ └── index.scss │ ├── cell │ │ ├── index.ts │ │ └── cell.ts │ ├── divider │ │ ├── index.ts │ │ └── divider.ts │ ├── drag │ │ ├── index.ts │ │ ├── index.scss │ │ └── drag.ts │ ├── ecard │ │ └── index.ts │ ├── empty │ │ ├── index.ts │ │ ├── empty.ts │ │ └── index.scss │ ├── icon │ │ ├── index.ts │ │ └── icon.ts │ ├── list │ │ ├── index.ts │ │ ├── index.scss │ │ ├── type.ts │ │ └── list.ts │ ├── navbar │ │ └── index.ts │ ├── picker │ │ └── index.ts │ ├── sku │ │ ├── index.ts │ │ └── index.scss │ ├── step │ │ ├── index.ts │ │ └── step.ts │ ├── steps │ │ ├── index.ts │ │ ├── index.scss │ │ └── steps.ts │ ├── sticky │ │ ├── index.ts │ │ ├── index.scss │ │ └── sticky.ts │ ├── swipe │ │ ├── index.ts │ │ ├── index.scss │ │ └── swipe.ts │ ├── switch │ │ ├── index.ts │ │ └── switch.ts │ ├── tabbar │ │ ├── index.ts │ │ ├── type.ts │ │ ├── index.scss │ │ └── tabbar.ts │ ├── tabpane │ │ ├── index.ts │ │ ├── index.scss │ │ └── tabpane.ts │ ├── tag │ │ ├── index.ts │ │ └── tag.ts │ ├── _constants │ │ ├── prefix.ts │ │ ├── id.ts │ │ ├── index.ts │ │ └── types.ts │ ├── backtop │ │ ├── index.ts │ │ ├── index.scss │ │ └── backtop.ts │ ├── barrage │ │ ├── index.ts │ │ └── barrage.ts │ ├── category │ │ ├── index.ts │ │ └── category.ts │ ├── checkbox │ │ ├── index.ts │ │ └── checkbox.ts │ ├── comment │ │ └── index.ts │ ├── countup │ │ └── index.ts │ ├── datepicker │ │ ├── index.scss │ │ ├── index.ts │ │ └── type.ts │ ├── fixednav │ │ ├── index.ts │ │ └── fixednav.ts │ ├── form │ │ ├── index.scss │ │ ├── index.ts │ │ ├── types.ts │ │ └── form.ts │ ├── giftbox │ │ ├── index.ts │ │ └── giftbox.ts │ ├── griditem │ │ ├── index.ts │ │ └── griditem.ts │ ├── hiteggs │ │ ├── index.ts │ │ └── hiteggs.ts │ ├── indicator │ │ ├── index.ts │ │ ├── indicator.ts │ │ ├── index.scss │ │ └── indicator.vue │ ├── invoice │ │ ├── index.ts │ │ ├── invoice.ts │ │ └── index.scss │ ├── marquee │ │ ├── index.ts │ │ └── marquee.ts │ ├── menuitem │ │ ├── index.ts │ │ └── menuitem.ts │ ├── overlay │ │ ├── index.ts │ │ ├── index.scss │ │ └── overlay.ts │ ├── pagination │ │ ├── index.ts │ │ └── pagination.ts │ ├── radiogroup │ │ ├── index.ts │ │ ├── index.scss │ │ ├── radiogroup.ts │ │ └── radiogroup.vue │ ├── searchbar │ │ └── index.ts │ ├── sidenavbar │ │ ├── index.ts │ │ ├── index.scss │ │ ├── sidenavbar.ts │ │ └── sidenavbar.vue │ ├── swiper │ │ ├── index.ts │ │ └── index.scss │ ├── tabbaritem │ │ ├── index.ts │ │ └── tabbaritem.ts │ ├── textarea │ │ ├── index.ts │ │ └── type.ts │ ├── timedetail │ │ ├── index.ts │ │ └── timedetail.ts │ ├── timepannel │ │ ├── index.ts │ │ ├── timepannel.ts │ │ ├── index.scss │ │ └── timepannel.vue │ ├── timeselect │ │ ├── index.ts │ │ └── timeselect.ts │ ├── trendarrow │ │ ├── index.ts │ │ ├── index.scss │ │ └── trendarrow.ts │ ├── watermark │ │ ├── index.ts │ │ └── index.scss │ ├── avatargroup │ │ ├── index.ts │ │ ├── index.scss │ │ └── avatargroup.ts │ ├── calendar │ │ ├── index.ts │ │ └── index.scss │ ├── calendaritem │ │ └── index.ts │ ├── cascader │ │ ├── index.ts │ │ └── types.ts │ ├── categorypane │ │ ├── index.ts │ │ └── categorypane.ts │ ├── cellgroup │ │ ├── index.ts │ │ ├── cellgroup.ts │ │ └── cellgroup.vue │ ├── codeinput │ │ └── index.ts │ ├── ellipsis │ │ ├── index.ts │ │ ├── index.scss │ │ └── ellipsis.ts │ ├── guessgift │ │ ├── index.ts │ │ ├── guessgift.ts │ │ └── index.scss │ ├── inputnumber │ │ └── index.ts │ ├── noticebar │ │ └── index.ts │ ├── shakedice │ │ ├── index.ts │ │ └── shakedice.ts │ ├── signature │ │ ├── index.ts │ │ ├── index.scss │ │ └── signature.ts │ ├── skeleton │ │ ├── index.ts │ │ └── skeleton.ts │ ├── swiperitem │ │ ├── index.ts │ │ ├── index.scss │ │ └── swiperitem.ts │ ├── actionsheet │ │ └── index.ts │ ├── addresslist │ │ ├── index.ts │ │ ├── index.scss │ │ └── addresslist.ts │ ├── cascaderitem │ │ ├── index.ts │ │ └── index.scss │ ├── circleprogress │ │ ├── index.ts │ │ ├── index.scss │ │ └── circleprogress.ts │ ├── collapseitem │ │ ├── index.ts │ │ └── collapseitem.ts │ ├── dollmachine │ │ ├── index.ts │ │ └── dollmachine.ts │ ├── imagepreview │ │ ├── index.ts │ │ └── types.ts │ ├── loadingpage │ │ ├── index.ts │ │ ├── index.scss │ │ └── loadingpage.ts │ ├── numberkeyboard │ │ └── index.ts │ ├── shortpassword │ │ ├── index.ts │ │ └── shortpassword.ts │ ├── sidenavbaritem │ │ ├── index.ts │ │ ├── sidenavbaritem.ts │ │ └── index.scss │ ├── subsidenavbar │ │ ├── index.ts │ │ └── subsidenavbar.ts │ ├── infiniteloading │ │ ├── index.ts │ │ └── index.scss │ ├── input │ │ ├── index.ts │ │ ├── util.ts │ │ └── type.ts │ ├── table │ │ ├── index.ts │ │ ├── types.ts │ │ ├── renderColumn.ts │ │ └── table.ts │ ├── address │ │ ├── index.ts │ │ └── type.ts │ ├── elevator │ │ ├── index.ts │ │ ├── type.ts │ │ └── elevator.ts │ ├── popup │ │ └── index.ts │ ├── progress │ │ ├── index.ts │ │ ├── types.ts │ │ └── progress.ts │ ├── formitem │ │ ├── index.ts │ │ ├── types.ts │ │ └── formitem.ts │ ├── popover │ │ ├── index.ts │ │ └── type.ts │ ├── pickercolumn │ │ ├── index.ts │ │ ├── types.ts │ │ └── pickercolumn.ts │ ├── turntable │ │ ├── index.ts │ │ └── type.ts │ ├── button │ │ ├── index.ts │ │ └── type.ts │ ├── countdown │ │ ├── index.ts │ │ └── index.scss │ ├── uploader │ │ ├── index.ts │ │ └── type.ts │ ├── dialog │ │ ├── index.ts │ │ └── type.ts │ ├── toast │ │ ├── index.ts │ │ └── types.ts │ ├── notify │ │ ├── index.ts │ │ ├── type.ts │ │ ├── index.scss │ │ └── notify.ts │ ├── transition │ │ ├── index.ts │ │ ├── index.scss │ │ ├── types.ts │ │ └── transition.ts │ ├── _utils │ │ ├── pxCheck.ts │ │ ├── index.ts │ │ ├── raf.ts │ │ └── interceptor.ts │ ├── _hooks │ │ ├── useRelation.ts │ │ ├── useExpose.ts │ │ ├── index.ts │ │ ├── useRect.ts │ │ ├── useLockScroll.ts │ │ ├── useRouter.ts │ │ ├── useStyle.ts │ │ └── useInject.ts │ ├── skuheader │ │ └── index.scss │ └── skuoperate │ │ └── index.scss │ ├── src │ └── index.ts │ ├── styles │ ├── mixins │ │ ├── index.scss │ │ ├── text-ellipsis.scss │ │ └── make-animation.scss │ ├── reset.css │ ├── index.scss │ ├── iconfont │ │ ├── iconfont.eot │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.woff2 │ └── animation │ │ ├── index.scss │ │ ├── rotate.scss │ │ ├── ease.scss │ │ ├── drop.scss │ │ └── zoom.scss │ ├── _locale │ ├── index.ts │ ├── README.md │ └── locale.ts │ ├── build.config.ts │ ├── tsconfig.json │ └── LICENSE ├── example ├── src │ ├── store │ │ ├── modules │ │ │ ├── index.ts │ │ │ └── app │ │ │ │ └── index.ts │ │ └── index.ts │ ├── static │ │ ├── logo.png │ │ ├── logo-red.png │ │ └── nutui-uniapp_logo.png │ ├── styles │ │ ├── reset.css │ │ └── app.scss │ ├── shime-uni.d.ts │ ├── env.d.ts │ ├── theme.json │ ├── components.d.ts │ ├── main.ts │ ├── components │ │ └── ThemeSwitch.vue │ ├── pages │ │ └── demo │ │ │ ├── bingo │ │ │ ├── hiteggs │ │ │ │ └── index.vue │ │ │ └── giftbox │ │ │ │ └── index.vue │ │ │ ├── exhibition │ │ │ └── loadingpage │ │ │ │ └── index.vue │ │ │ └── business │ │ │ └── barrage │ │ │ └── index.vue │ └── manifest.json ├── eslint.config.js ├── .gitignore ├── index.html ├── tsconfig.json └── pages.config.ts ├── .npmrc ├── pnpm-workspace.yaml ├── docs ├── public │ ├── logo-red.png │ ├── pwa-192x192.png │ └── pwa-512x512.png ├── guide │ ├── changelog.md │ ├── faq.md │ ├── i18n.md │ ├── overview.md │ └── theme.md ├── components.d.ts ├── tsconfig.json ├── uno.config.ts ├── .vitepress │ ├── theme │ │ └── index.ts │ └── scripts │ │ └── pwa.ts ├── components │ ├── template.md │ ├── feedback │ │ └── drag.md │ └── bingo │ │ └── giftbox.md ├── package.json ├── vite.config.ts └── index.md ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── feature_request_template.yml ├── workflows │ ├── release.yml │ └── issue-labeled.yml └── pull_request_template.md ├── scripts ├── build.ts └── uni.ts ├── eslint.config.js ├── .stylelintignore ├── .markdownlint.json ├── tsconfig.json ├── .vscode └── extensions.json ├── .gitignore ├── .stylelintrc ├── LICENSE └── CODE_OF_CONDUCT.md /packages/nutui/components/collapse/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/nutui/components/swipegroup/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/nutui/components/checkboxgroup/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/nutui/components/configprovider/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/src/store/modules/index.ts: -------------------------------------------------------------------------------- 1 | export * from './app' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/badge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './badge' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/card/index.ts: -------------------------------------------------------------------------------- 1 | export * from './card' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/col/index.ts: -------------------------------------------------------------------------------- 1 | export * from './col' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/grid/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grid' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/menu/index.ts: -------------------------------------------------------------------------------- 1 | export * from './menu' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/price/index.ts: -------------------------------------------------------------------------------- 1 | export * from './price' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/radio/index.ts: -------------------------------------------------------------------------------- 1 | export * from './radio' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/range/index.ts: -------------------------------------------------------------------------------- 1 | export * from './range' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/rate/index.ts: -------------------------------------------------------------------------------- 1 | export * from './rate' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/row/index.ts: -------------------------------------------------------------------------------- 1 | export * from './row' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/tabs/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tabs' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/tour/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tour' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/animate/index.ts: -------------------------------------------------------------------------------- 1 | export * from './animate' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/avatar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './avatar' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/cell/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './cell' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/divider/index.ts: -------------------------------------------------------------------------------- 1 | export * from './divider' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/drag/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './drag' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/ecard/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './ecard' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/empty/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './empty' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/icon/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './icon' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/list/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './list' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/navbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './navbar' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/picker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './picker' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/sku/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './sku' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/step/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './step' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/steps/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './steps' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/sticky/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sticky' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/swipe/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './swipe' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/switch/index.ts: -------------------------------------------------------------------------------- 1 | export * from './switch' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/tabbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tabbar' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/tabpane/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tabpane' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/tag/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './tag' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/_constants/prefix.ts: -------------------------------------------------------------------------------- 1 | export const PREFIX = 'nut' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/backtop/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './backtop' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/barrage/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './barrage' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/category/index.ts: -------------------------------------------------------------------------------- 1 | export * from './category' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/checkbox/index.ts: -------------------------------------------------------------------------------- 1 | export * from './checkbox' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/comment/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './comment' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/countup/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './countup' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/datepicker/index.scss: -------------------------------------------------------------------------------- 1 | @import '../picker/index'; 2 | -------------------------------------------------------------------------------- /packages/nutui/components/fixednav/index.ts: -------------------------------------------------------------------------------- 1 | export * from './fixednav' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/form/index.scss: -------------------------------------------------------------------------------- 1 | @import '../cellgroup/index'; 2 | -------------------------------------------------------------------------------- /packages/nutui/components/giftbox/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './giftbox' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/griditem/index.ts: -------------------------------------------------------------------------------- 1 | export * from './griditem' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/hiteggs/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './hiteggs' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/indicator/index.ts: -------------------------------------------------------------------------------- 1 | export * from './indicator' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/invoice/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './invoice' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/marquee/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './marquee' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/menuitem/index.ts: -------------------------------------------------------------------------------- 1 | export * from './menuitem' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/overlay/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './overlay' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/pagination/index.ts: -------------------------------------------------------------------------------- 1 | export * from './pagination' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/radiogroup/index.ts: -------------------------------------------------------------------------------- 1 | export * from './radiogroup' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/searchbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './searchbar' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/sidenavbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sidenavbar' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/swiper/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './swiper' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/tabbaritem/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tabbaritem' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/textarea/index.ts: -------------------------------------------------------------------------------- 1 | export * from './textarea' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/timedetail/index.ts: -------------------------------------------------------------------------------- 1 | export * from './timedetail' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/timepannel/index.ts: -------------------------------------------------------------------------------- 1 | export * from './timepannel' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/timeselect/index.ts: -------------------------------------------------------------------------------- 1 | export * from './timeselect' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/trendarrow/index.ts: -------------------------------------------------------------------------------- 1 | export * from './trendarrow' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/watermark/index.ts: -------------------------------------------------------------------------------- 1 | export * from './watermark' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/avatargroup/index.ts: -------------------------------------------------------------------------------- 1 | export * from './avatargroup' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/calendar/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './calendar' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/calendaritem/index.ts: -------------------------------------------------------------------------------- 1 | export * from './calendaritem' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/cascader/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './cascader' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/categorypane/index.ts: -------------------------------------------------------------------------------- 1 | export * from './categorypane' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/cellgroup/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './cellgroup' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/codeinput/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './codeinput' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/collapse/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './collapse' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/ellipsis/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './ellipsis' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/guessgift/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './guessgift' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/inputnumber/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inputnumber' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/noticebar/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './noticebar' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/shakedice/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './shakedice' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/signature/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './signature' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/skeleton/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './skeleton' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/swipegroup/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './swipegroup' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/swiperitem/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './swiperitem' 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | shell-emulator=true -------------------------------------------------------------------------------- /packages/nutui/components/actionsheet/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './actionsheet' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/addresslist/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './addresslist' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/calendar/index.scss: -------------------------------------------------------------------------------- 1 | @import '../popup/index'; 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/nutui/components/cascaderitem/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './cascaderitem' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/checkboxgroup/index.ts: -------------------------------------------------------------------------------- 1 | export * from './checkboxgroup' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/circleprogress/index.ts: -------------------------------------------------------------------------------- 1 | export * from './circleprogress' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/collapseitem/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './collapseitem' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/dollmachine/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './dollmachine' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/imagepreview/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './imagepreview' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/loadingpage/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './loadingpage' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/numberkeyboard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './numberkeyboard' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/shortpassword/index.ts: -------------------------------------------------------------------------------- 1 | export * from './shortpassword' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/sidenavbaritem/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sidenavbaritem' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/subsidenavbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './subsidenavbar' 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/**' 3 | - docs 4 | - example 5 | -------------------------------------------------------------------------------- /packages/nutui/components/configprovider/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './configprovider' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/infiniteloading/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './infiniteloading' 2 | -------------------------------------------------------------------------------- /packages/nutui/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '../components' 2 | export * from './resolver' 3 | -------------------------------------------------------------------------------- /packages/nutui/styles/mixins/index.scss: -------------------------------------------------------------------------------- 1 | @import 'make-animation'; 2 | @import 'text-ellipsis'; -------------------------------------------------------------------------------- /packages/nutui/styles/reset.css: -------------------------------------------------------------------------------- 1 | html { 2 | -webkit-tap-highlight-color: transparent; 3 | } -------------------------------------------------------------------------------- /packages/nutui/_locale/index.ts: -------------------------------------------------------------------------------- 1 | export * from './locale' 2 | export * from './useTranslate' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/input/index.ts: -------------------------------------------------------------------------------- 1 | export * from './input' 2 | export * from './type' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/swiperitem/index.scss: -------------------------------------------------------------------------------- 1 | .nut-swiper-item { 2 | height: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /packages/nutui/components/table/index.ts: -------------------------------------------------------------------------------- 1 | export * from './table' 2 | export * from './types' 3 | -------------------------------------------------------------------------------- /docs/public/logo-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/nutui-uniapp/main/docs/public/logo-red.png -------------------------------------------------------------------------------- /example/eslint.config.js: -------------------------------------------------------------------------------- 1 | import antfu from '@antfu/eslint-config' 2 | 3 | export default antfu() 4 | -------------------------------------------------------------------------------- /packages/nutui/components/address/index.ts: -------------------------------------------------------------------------------- 1 | export * from './address' 2 | export * from './type' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/elevator/index.ts: -------------------------------------------------------------------------------- 1 | export * from './elevator' 2 | export * from './type' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/form/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './form' 2 | export * from './types' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/popup/index.ts: -------------------------------------------------------------------------------- 1 | export * from './use-popup' 2 | export * from './popup' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/progress/index.ts: -------------------------------------------------------------------------------- 1 | export * from './progress' 2 | export * from './types' 3 | -------------------------------------------------------------------------------- /docs/public/pwa-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/nutui-uniapp/main/docs/public/pwa-192x192.png -------------------------------------------------------------------------------- /docs/public/pwa-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/nutui-uniapp/main/docs/public/pwa-512x512.png -------------------------------------------------------------------------------- /example/src/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/nutui-uniapp/main/example/src/static/logo.png -------------------------------------------------------------------------------- /packages/nutui/components/datepicker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './datepicker' 2 | export * from './type' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/formitem/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './formitem' 2 | export * from './types' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/popover/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './popover' 2 | export * from './type' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/_constants/id.ts: -------------------------------------------------------------------------------- 1 | export const refRandomId = Math.random().toString(36).slice(-8) 2 | -------------------------------------------------------------------------------- /packages/nutui/components/pickercolumn/index.ts: -------------------------------------------------------------------------------- 1 | export * from './pickercolumn' 2 | export * from './types' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/turntable/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './turntable' 2 | export type * from './type' 3 | -------------------------------------------------------------------------------- /example/src/static/logo-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/nutui-uniapp/main/example/src/static/logo-red.png -------------------------------------------------------------------------------- /packages/nutui/components/_constants/index.ts: -------------------------------------------------------------------------------- 1 | export * from './prefix' 2 | export * from './types' 3 | export * from './id' 4 | -------------------------------------------------------------------------------- /packages/nutui/components/button/index.ts: -------------------------------------------------------------------------------- 1 | export type { ButtonProps, ButtonEmits } from './button' 2 | export * from './type' 3 | -------------------------------------------------------------------------------- /packages/nutui/styles/index.scss: -------------------------------------------------------------------------------- 1 | @import './iconfont/iconfont.css'; 2 | @import './reset.css'; 3 | @import './animation/index' 4 | -------------------------------------------------------------------------------- /example/src/static/nutui-uniapp_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/nutui-uniapp/main/example/src/static/nutui-uniapp_logo.png -------------------------------------------------------------------------------- /packages/nutui/components/cascaderitem/index.scss: -------------------------------------------------------------------------------- 1 | @import '../cascader/index'; 2 | @import '../tabs/index'; 3 | @import '../tabpane/index'; -------------------------------------------------------------------------------- /packages/nutui/components/countdown/index.ts: -------------------------------------------------------------------------------- 1 | export type { CountDownPropsProps, CountdownEmits, CountdownInst } from './countdown' 2 | -------------------------------------------------------------------------------- /packages/nutui/components/swiperitem/swiperitem.ts: -------------------------------------------------------------------------------- 1 | export interface SwiperItemInst { 2 | setOffset: (offset: number) => void 3 | } 4 | -------------------------------------------------------------------------------- /packages/nutui/components/uploader/index.ts: -------------------------------------------------------------------------------- 1 | export * from './uploader' 2 | export * from './type' 3 | export * from './use-uploader' 4 | -------------------------------------------------------------------------------- /packages/nutui/components/dialog/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './dialog' 2 | export type * from './type' 3 | export * from './use-dialog' 4 | -------------------------------------------------------------------------------- /packages/nutui/components/toast/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './use-toast' 2 | export type * from './types' 3 | export type * from './toast' 4 | -------------------------------------------------------------------------------- /packages/nutui/styles/iconfont/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/nutui-uniapp/main/packages/nutui/styles/iconfont/iconfont.eot -------------------------------------------------------------------------------- /packages/nutui/styles/iconfont/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/nutui-uniapp/main/packages/nutui/styles/iconfont/iconfont.ttf -------------------------------------------------------------------------------- /packages/nutui/styles/iconfont/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/nutui-uniapp/main/packages/nutui/styles/iconfont/iconfont.woff -------------------------------------------------------------------------------- /packages/nutui/components/notify/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './notify' 2 | export type * from './type' 3 | export type * from './use-notify' 4 | -------------------------------------------------------------------------------- /packages/nutui/components/transition/index.ts: -------------------------------------------------------------------------------- 1 | export * from './transition' 2 | export * from './use-transition' 3 | export type * from './types' 4 | -------------------------------------------------------------------------------- /packages/nutui/styles/iconfont/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/nutui-uniapp/main/packages/nutui/styles/iconfont/iconfont.woff2 -------------------------------------------------------------------------------- /example/src/styles/reset.css: -------------------------------------------------------------------------------- 1 | body { 2 | 3 | line-height:1; 4 | 5 | } 6 | 7 | :focus { 8 | 9 | outline: 1; 10 | 11 | } 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/nutui/components/progress/types.ts: -------------------------------------------------------------------------------- 1 | export type ProgressSize = 'small' | 'base' | 'large' 2 | export type ProgressStatus = 'text' | 'active' | 'icon' 3 | -------------------------------------------------------------------------------- /packages/nutui/components/steps/index.scss: -------------------------------------------------------------------------------- 1 | .nut-steps { 2 | display: flex; 3 | } 4 | 5 | .nut-steps-vertical { 6 | flex-flow: column; 7 | height: 100%; 8 | } 9 | -------------------------------------------------------------------------------- /packages/nutui/components/countdown/index.scss: -------------------------------------------------------------------------------- 1 | .nut-countdown { 2 | display: $countdown-display; 3 | font-size: $countdown-font-size; 4 | color: $countdown-color; 5 | } 6 | -------------------------------------------------------------------------------- /packages/nutui/components/_utils/pxCheck.ts: -------------------------------------------------------------------------------- 1 | export function pxCheck(value: string | number): string { 2 | return Number.isNaN(Number(value)) ? String(value) : `${value}px` 3 | } 4 | -------------------------------------------------------------------------------- /packages/nutui/components/turntable/type.ts: -------------------------------------------------------------------------------- 1 | export interface TPrizeItem { 2 | id: string | number 3 | prizeName: string 4 | prizeColor: string 5 | prizeImg: string 6 | } 7 | -------------------------------------------------------------------------------- /example/src/shime-uni.d.ts: -------------------------------------------------------------------------------- 1 | export {} 2 | 3 | declare module 'vue' { 4 | type Hooks = App.AppInstance & Page.PageInstance 5 | interface ComponentCustomOptions extends Hooks {} 6 | } 7 | -------------------------------------------------------------------------------- /packages/nutui/components/textarea/type.ts: -------------------------------------------------------------------------------- 1 | export type ConfirmTextType = 'send' | 'search' | 'next' | 'go' | 'done' | 'return' 2 | 3 | export type AdjustKeyboardTo = 'cursor' | 'bottom' 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 🤖 常见问题 QA 4 | url: https://nutui-uniapp.netlify.app/guide/faq.html 5 | about: 这里可能会有解决方案。 6 | -------------------------------------------------------------------------------- /packages/nutui/styles/animation/index.scss: -------------------------------------------------------------------------------- 1 | // Animation 2 | @import 'fade'; 3 | @import 'zoom'; 4 | @import 'ease'; 5 | @import 'drop'; 6 | @import 'rotate'; 7 | @import 'slide'; 8 | @import 'icon'; -------------------------------------------------------------------------------- /scripts/build.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra' 2 | 3 | fs.removeSync('docs/.vitepress/dist/ui') 4 | fs.ensureDirSync('docs/.vitepress/dist/ui') 5 | 6 | fs.copySync('example/dist/build/h5', 'docs/.vitepress/dist/ui') 7 | -------------------------------------------------------------------------------- /packages/nutui/components/transition/index.scss: -------------------------------------------------------------------------------- 1 | // .nut-transition { 2 | // transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 3 | // transition-duration: 150ms; 4 | // transition-property: all; 5 | // } 6 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import antfu from '@antfu/eslint-config' 2 | 3 | export default antfu({ 4 | overrides: { 5 | vue: { 6 | 'vue/component-name-in-template-casing': ['off'], 7 | }, 8 | }, 9 | }) 10 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | dist 2 | es 3 | lib 4 | css 5 | example 6 | public 7 | cache 8 | node_modules 9 | .husky 10 | 11 | docs/.vitepress/theme 12 | 13 | *.js 14 | *.cjs 15 | *.mjs 16 | *.ts 17 | *.tsx 18 | *.svg 19 | *.gif 20 | *.md -------------------------------------------------------------------------------- /packages/nutui/components/sticky/index.scss: -------------------------------------------------------------------------------- 1 | .nut-sticky { 2 | /* #ifdef APP-PLUS || MP-WEIXIN || MP-TOUTIAO */ 3 | // 此处默认写sticky属性,是为了给微信和APP通过uni.createSelectorQuery查询是否支持css sticky使用 4 | position: sticky; 5 | 6 | /* #endif */ 7 | } -------------------------------------------------------------------------------- /packages/nutui/styles/animation/rotate.scss: -------------------------------------------------------------------------------- 1 | @keyframes rotation { 2 | 0% { 3 | transform: rotate(0deg); 4 | } 5 | 6 | 100% { 7 | transform: rotate(360deg); 8 | } 9 | } 10 | 11 | @include make-animation(nutRotate); 12 | -------------------------------------------------------------------------------- /packages/nutui/components/elevator/type.ts: -------------------------------------------------------------------------------- 1 | export interface ElevatorData { 2 | name?: string 3 | id?: number | string 4 | [key: string]: any 5 | } 6 | 7 | export interface ElevatorInst { 8 | scrollTo: (val: number) => void 9 | } 10 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD001": false, 3 | "MD003": false, 4 | "MD013": false, 5 | "MD022": false, 6 | "MD024": false, 7 | "MD025": false, 8 | "MD033": false, 9 | "MD036": false, 10 | "MD041": false, 11 | "MD050": false 12 | } -------------------------------------------------------------------------------- /example/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue' 5 | 6 | const component: DefineComponent, object, any> 7 | export default component 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.json", 3 | "compilerOptions": { 4 | "types": [ 5 | "node", 6 | "vite/client", 7 | "@dcloudio/types", 8 | "@uni-helper/uni-app-types" 9 | ] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /example/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia' 2 | 3 | import type { App } from 'vue' 4 | 5 | export const pinia = createPinia() 6 | 7 | export async function setupStore(app: App) { 8 | app.use(pinia) 9 | } 10 | 11 | export * from './modules' 12 | -------------------------------------------------------------------------------- /docs/guide/changelog.md: -------------------------------------------------------------------------------- 1 | # 更新日志 2 | 3 | ## 最新版本 4 | 5 | [](https://www.npmjs.com/package/nutui-uniapp) 6 | 7 | 您可以订阅此提要以获取新版本通知:[更新日志](https://github.com/nutui-uniapp/nutui-uniapp/releases) 8 | -------------------------------------------------------------------------------- /packages/nutui/components/watermark/index.scss: -------------------------------------------------------------------------------- 1 | .nut-watermark { 2 | position: absolute; 3 | inset: 0; 4 | z-index: $watermark-z-index; 5 | pointer-events: none; 6 | background-repeat: repeat; 7 | 8 | &-full-page { 9 | position: fixed; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/nutui/components/_constants/types.ts: -------------------------------------------------------------------------------- 1 | export const animationName = { 2 | center: 'fade', 3 | top: 'slide-down', 4 | bottom: 'slide-up', 5 | left: 'slide-left', 6 | right: 'slide-right', 7 | } 8 | 9 | export type Position = (keyof typeof animationName) 10 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "uni-helper.uni-highlight-vscode", 5 | "uni-helper.uni-helper-vscode", 6 | "stylelint.vscode-stylelint", 7 | "vue.vscode-typescript-vue-plugin", 8 | "vue.volar" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/nutui/components/overlay/index.scss: -------------------------------------------------------------------------------- 1 | .nut-overlay { 2 | position: fixed; 3 | inset: 0; 4 | top: 0; 5 | left: 0; 6 | width: 100%; 7 | height: 100%; 8 | background: $overlay-bg-color; 9 | } 10 | 11 | .nut-overflow-hidden { 12 | overflow: hidden !important; 13 | } 14 | -------------------------------------------------------------------------------- /packages/nutui/components/_utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './pxCheck' 2 | export * from './env' 3 | export * from './common' 4 | export * from './date' 5 | export * from './props' 6 | export * from './style' 7 | export * from './is' 8 | export * from './interceptor' 9 | export * from './raf' 10 | -------------------------------------------------------------------------------- /packages/nutui/components/cellgroup/cellgroup.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const cellgroupProps = { 4 | title: { type: String, default: '' }, 5 | desc: { type: String, default: '' }, 6 | } 7 | 8 | export type CellGroupProps = ExtractPropTypes 9 | -------------------------------------------------------------------------------- /packages/nutui/components/swipegroup/swipegroup.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const swipegroupProps = { 4 | lock: { 5 | type: Boolean, 6 | default: false, 7 | }, 8 | } 9 | 10 | export type SwipeGroupProps = ExtractPropTypes 11 | -------------------------------------------------------------------------------- /packages/nutui/components/tabbar/type.ts: -------------------------------------------------------------------------------- 1 | export interface provideData { 2 | children: any[] 3 | size: string 4 | modelValue: string | number 5 | unactiveColor: string 6 | activeColor: string 7 | dot: boolean 8 | changeIndex: (index: number, active: number | string) => void 9 | } 10 | -------------------------------------------------------------------------------- /packages/nutui/components/tabs/type.ts: -------------------------------------------------------------------------------- 1 | export interface provideData { 2 | children: any[] 3 | size: string 4 | modelValue: string | number 5 | unactiveColor: string 6 | activeColor: string 7 | dot: boolean 8 | changeIndex: (index: number, active: number | string) => void 9 | } 10 | -------------------------------------------------------------------------------- /packages/nutui/components/button/type.ts: -------------------------------------------------------------------------------- 1 | export type ButtonType = 'default' | 'primary' | 'info' | 'success' | 'warning' | 'danger' 2 | export type ButtonSize = 'large' | 'normal' | 'small' | 'mini' 3 | export type ButtonShape = 'square' | 'round' 4 | export type ButtonFormType = 'button' | 'submit' | 'reset' 5 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | *.local 14 | 15 | # Editor directories and files 16 | .idea 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? -------------------------------------------------------------------------------- /packages/nutui/components/datepicker/type.ts: -------------------------------------------------------------------------------- 1 | import type { PickerOption } from '../pickercolumn/types' 2 | 3 | export type Formatter = ( 4 | type: string, 5 | option: PickerOption 6 | ) => PickerOption 7 | export type Filter = ( 8 | columnType: string, 9 | options: PickerOption[] 10 | ) => PickerOption[] 11 | -------------------------------------------------------------------------------- /packages/nutui/components/_hooks/useRelation.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentPublicInstance } from 'vue' 2 | import { getCurrentInstance } from 'vue' 3 | 4 | export function useExtend(apis: T) { 5 | const instance = getCurrentInstance() 6 | if (instance) 7 | Object.assign(instance.proxy as ComponentPublicInstance, apis) 8 | } 9 | -------------------------------------------------------------------------------- /packages/nutui/components/animate/type.ts: -------------------------------------------------------------------------------- 1 | export type AnimateType = 2 | | 'shake' 3 | | 'ripple' 4 | | 'breath' 5 | | 'float' 6 | | 'slide-right' 7 | | 'slide-left' 8 | | 'slide-top' 9 | | 'slide-bottom' 10 | | 'jump' 11 | | 'twinkle' 12 | | 'flicker' 13 | export type AnimateAction = 'initial' | 'click' | '' 14 | -------------------------------------------------------------------------------- /packages/nutui/components/_hooks/useExpose.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentPublicInstance } from 'vue' 2 | import { getCurrentInstance } from 'vue' 3 | 4 | export function useExpose(apis: Record) { 5 | const instance = getCurrentInstance() 6 | if (instance) 7 | Object.assign(instance.proxy as ComponentPublicInstance, apis) 8 | } 9 | -------------------------------------------------------------------------------- /docs/components.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // Generated by vite-plugin-uni-components 5 | // Read more: https://github.com/vuejs/core/pull/3399 6 | import '@vue/runtime-core' 7 | 8 | export {} 9 | 10 | declare module '@vue/runtime-core' { 11 | export interface GlobalComponents { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/nutui/components/col/col.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const colProps = { 4 | span: { 5 | type: [String, Number], 6 | default: '24', 7 | }, 8 | offset: { 9 | type: [String, Number], 10 | default: '0', 11 | }, 12 | } 13 | 14 | export type ColProps = ExtractPropTypes 15 | -------------------------------------------------------------------------------- /packages/nutui/components/configprovider/configprovider.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export const configProviderProps = { 4 | theme: { type: String as PropType<'dark' | string>, default: '' }, 5 | themeVars: { type: Object, default: {} }, 6 | } 7 | 8 | export type ConfigProviderProps = ExtractPropTypes 9 | -------------------------------------------------------------------------------- /packages/nutui/components/_hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useStyle' 2 | export * from './useLockScroll' 3 | export * from './useRect' 4 | export * from './useTouch' 5 | export * from './useProvide' 6 | export * from './useInject' 7 | export * from './useRouter' 8 | export * from './useExpose' 9 | export * from './useRelation' 10 | export * from './useSelectorQuery' 11 | -------------------------------------------------------------------------------- /packages/nutui/components/_hooks/useRect.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentInternalInstance } from 'vue' 2 | import { useSelectorQuery } from './useSelectorQuery' 3 | 4 | export function useRect(id: string, instance?: ComponentInternalInstance): Promise { 5 | const { getSelectorNodeInfo } = useSelectorQuery(instance) 6 | return getSelectorNodeInfo(`#${id}`) 7 | } 8 | -------------------------------------------------------------------------------- /packages/nutui/components/sidenavbar/index.scss: -------------------------------------------------------------------------------- 1 | .nut-side-navbar { 2 | display: block; 3 | height: 100%; 4 | overflow: auto; 5 | 6 | &__content { 7 | position: relative; 8 | display: block; 9 | background-color: $sidenavbar-content-bg-color; 10 | 11 | &__list { 12 | display: block; 13 | width: 100%; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/nutui/components/sidenavbar/sidenavbar.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const SIDEN_NAVBAR_KEY = Symbol('sidennavbar') 4 | 5 | export const sidenavbarProps = { 6 | offset: { 7 | type: [String, Number], 8 | default: 15, 9 | }, 10 | } 11 | 12 | export type SidenavbarProps = ExtractPropTypes 13 | -------------------------------------------------------------------------------- /packages/nutui/components/formitem/types.ts: -------------------------------------------------------------------------------- 1 | export class FormItemRuleWithoutValidator { 2 | regex?: RegExp 3 | required?: boolean 4 | message!: string; 5 | [key: string]: any; 6 | } 7 | 8 | export class FormItemRule extends FormItemRuleWithoutValidator { 9 | validator?: (value: any, ruleCfg?: FormItemRuleWithoutValidator) => Promise 10 | } 11 | -------------------------------------------------------------------------------- /packages/nutui/components/table/types.ts: -------------------------------------------------------------------------------- 1 | import type { VNode, VNodeChild } from 'vue' 2 | 3 | export interface TableColumnProps { 4 | key?: string 5 | title?: string 6 | align?: string 7 | stylehead?: string 8 | stylecolumn?: string 9 | sorter?: (row1: any, row2: any) => boolean 10 | render?: (rowData?: object, rowIndex?: number) => VNodeChild | string | VNode 11 | } 12 | -------------------------------------------------------------------------------- /packages/nutui/components/ellipsis/index.scss: -------------------------------------------------------------------------------- 1 | .nut-ellipsis { 2 | display: flex; 3 | 4 | .nut-ellipsis__text { 5 | display: inline; 6 | color: $ellipsis-expand-collapse-color; 7 | cursor: hand; 8 | } 9 | 10 | .nut-ellipsis__wordbreak { 11 | word-break: break-all; 12 | } 13 | } 14 | 15 | .nut-ellipsis__copy { 16 | position: absolute; 17 | top: -999999px; 18 | } 19 | -------------------------------------------------------------------------------- /packages/nutui/components/grid/index.scss: -------------------------------------------------------------------------------- 1 | .nut-theme-dark { 2 | .nut-grid { 3 | display: flex; 4 | flex-wrap: wrap; 5 | border: 0 solid $dark-background; 6 | } 7 | } 8 | 9 | 10 | 11 | .nut-grid { 12 | display: flex; 13 | flex-wrap: wrap; 14 | border: 0 solid $grid-border-color; 15 | 16 | &--border { 17 | border-top-width: 1px; 18 | border-left-width: 1px; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/nutui/components/avatargroup/index.scss: -------------------------------------------------------------------------------- 1 | .nut-avatar-group { 2 | position: relative; 3 | display: flex; 4 | flex: 0 0 auto; // 防止被压缩 5 | background-repeat: no-repeat; 6 | background-position: center center; 7 | background-size: 100% 100%; 8 | 9 | .nut-avatar { 10 | border: 1px solid #fff; 11 | 12 | &:not(:first-of-type) { 13 | margin-left: -8px; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.json", 3 | "compilerOptions": { 4 | "module": "esnext", 5 | "types": [ 6 | "vite/client" 7 | ] 8 | }, 9 | "include": [ 10 | "**/*.ts", 11 | "**/*.d.ts", 12 | "../docs/.vitepress/**/*.ts", 13 | "../docs/.vitepress/**/*.vue" 14 | ], 15 | "exclude": [ 16 | "**/dist/**", 17 | "**/node_modules/**" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/nutui/components/table/renderColumn.ts: -------------------------------------------------------------------------------- 1 | import type { PropType } from 'vue' 2 | import { defineComponent, h } from 'vue' 3 | 4 | export default defineComponent({ 5 | props: { 6 | slots: Array as PropType void | undefined>>, 7 | record: Object, 8 | }, 9 | setup(props: any) { 10 | return () => h('view', {}, props.slots[0] ? props.slots[0](props.record) : props.slots[1](props.record)) 11 | }, 12 | }) 13 | -------------------------------------------------------------------------------- /packages/nutui/components/radiogroup/index.scss: -------------------------------------------------------------------------------- 1 | .nut-radio-group { 2 | display: inline-block; 3 | 4 | .nut-radio { 5 | margin-bottom: 5px; 6 | } 7 | 8 | &--horizontal { 9 | .nut-radio { 10 | display: inline-flex !important; 11 | margin-right: 10px !important; 12 | 13 | &--round { 14 | .nut-radio__label { 15 | margin: 0 6px !important; 16 | } 17 | } 18 | 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/nutui/components/drag/index.scss: -------------------------------------------------------------------------------- 1 | .nut-drag { 2 | position: fixed; 3 | z-index: 9997 !important; 4 | display: inline-block; 5 | width: fit-content; 6 | height: fit-content; 7 | 8 | .nut-fixed-nav { 9 | position: relative !important; 10 | } 11 | } 12 | 13 | .nut-uni-drag { 14 | z-index: 9997 !important; 15 | 16 | // position: fixed; 17 | display: inline-block; 18 | width: fit-content; 19 | height: fit-content; 20 | } 21 | -------------------------------------------------------------------------------- /packages/nutui/styles/animation/ease.scss: -------------------------------------------------------------------------------- 1 | @keyframes nutEaseIn { 2 | 0% { 3 | opacity: 0; 4 | transform: scale(0.9); 5 | } 6 | 7 | 100% { 8 | opacity: 1; 9 | transform: scale(1); 10 | } 11 | } 12 | 13 | @keyframes nutEaseOut { 14 | 0% { 15 | opacity: 1; 16 | transform: scale(1); 17 | } 18 | 19 | 100% { 20 | opacity: 0; 21 | transform: scale(0.9); 22 | } 23 | } 24 | 25 | @include make-animation(nutEase); 26 | -------------------------------------------------------------------------------- /docs/uno.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, presetAttributify, presetIcons, presetUno } from 'unocss' 2 | 3 | export default defineConfig({ 4 | content: { 5 | 6 | }, 7 | presets: [ 8 | presetUno(), 9 | presetIcons({ 10 | scale: 1.2, 11 | warn: true, 12 | extraProperties: { 13 | 'display': 'inline-block', 14 | 'vertical-align': 'middle', 15 | }, 16 | }), 17 | presetAttributify(), 18 | ], 19 | }) 20 | -------------------------------------------------------------------------------- /example/src/theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "dark": { 3 | "navBgColor": "#191919", 4 | "navTxtStyle": "white", 5 | "bgColor": "#000", 6 | "bgTxtStyle": "light", 7 | "bgColorTop": "#000", 8 | "bgColorBottom": "#000" 9 | }, 10 | "light": { 11 | "navBgColor": "#FFFFFF", 12 | "navTxtStyle": "black", 13 | "bgColor": "#F3F4F6", 14 | "bgTxtStyle": "dark", 15 | "bgColorTop": "#F3F4F6", 16 | "bgColorBottom": "#F3F4F6" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/nutui/components/step/step.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const stepProps = { 4 | title: { 5 | type: String, 6 | default: '', 7 | }, 8 | content: { 9 | type: String, 10 | default: '', 11 | }, 12 | } 13 | 14 | export type StepProps = ExtractPropTypes 15 | 16 | export const stepEmits = { 17 | clickStep: (val: number) => true, 18 | } 19 | 20 | export type StepEmits = typeof stepEmits 21 | -------------------------------------------------------------------------------- /packages/nutui/components/trendarrow/index.scss: -------------------------------------------------------------------------------- 1 | .nut-trend-arrow { 2 | display: inline-block; 3 | font-size: $trendarrow-font-size; 4 | 5 | &-icon-before { 6 | margin-right: $trendarrow-before-icon-margin; 7 | } 8 | 9 | &-icon-after { 10 | margin-left: $trendarrow-before-icon-margin; 11 | } 12 | 13 | &-rate { 14 | display: inline; 15 | vertical-align: middle; 16 | } 17 | 18 | .nut-icon { 19 | vertical-align: middle; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/nutui/components/address/type.ts: -------------------------------------------------------------------------------- 1 | export interface RegionData { 2 | name: string 3 | [key: string]: any 4 | } 5 | 6 | export interface CustomRegionData { 7 | title: string 8 | list: any[] 9 | } 10 | 11 | export interface existRegionData { 12 | id?: string | number 13 | provinceName: string 14 | cityName: string 15 | countyName: string 16 | townName: string 17 | addressDetail: string 18 | selectedAddress: boolean 19 | [key: string]: any 20 | } 21 | -------------------------------------------------------------------------------- /packages/nutui/styles/animation/drop.scss: -------------------------------------------------------------------------------- 1 | @keyframes nutDropIn { 2 | 0% { 3 | opacity: 0; 4 | transform: scaleY(0.8); 5 | } 6 | 7 | 100% { 8 | opacity: 1; 9 | transform: scaleY(1); 10 | } 11 | } 12 | 13 | @keyframes nutDropOut { 14 | 0% { 15 | opacity: 1; 16 | transform: scaleY(1); 17 | } 18 | 19 | 100% { 20 | opacity: 0; 21 | transform: scaleY(0.8); 22 | } 23 | } 24 | 25 | // select、dropdown 26 | @include make-animation(nutDrop); 27 | -------------------------------------------------------------------------------- /packages/nutui/components/form/types.ts: -------------------------------------------------------------------------------- 1 | import type { FormItemRule } from '../formitem/types' 2 | 3 | export interface FormRules { 4 | [key: string]: FormItemRule[] 5 | } 6 | 7 | export interface FormRule { 8 | prop: string 9 | rules: FormItemRule[] 10 | } 11 | 12 | export interface ErrorMessage { 13 | prop: string 14 | message: string 15 | } 16 | 17 | export interface FormInst { 18 | reset: () => void 19 | submit: () => void 20 | validate: (customProp?: any) => Promise 21 | } 22 | -------------------------------------------------------------------------------- /packages/nutui/components/timedetail/timedetail.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export const timedetailProps = { 4 | times: { 5 | type: Array as PropType, 6 | default: () => { 7 | return [] 8 | }, 9 | }, 10 | } 11 | 12 | export type TimeDetailProps = ExtractPropTypes 13 | 14 | export const timedetailEmits = { 15 | select: (time: string) => true, 16 | } 17 | 18 | export type TimeDetailEmits = typeof timedetailEmits 19 | -------------------------------------------------------------------------------- /example/src/components.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // Generated by vite-plugin-uni-components 5 | // Read more: https://github.com/vuejs/core/pull/3399 6 | import '@vue/runtime-core' 7 | 8 | export {} 9 | 10 | declare module '@vue/runtime-core' { 11 | export interface GlobalComponents { 12 | DemoHeader: typeof import('./components/DemoHeader.vue')['default'] 13 | ThemeSwitch: typeof import('./components/ThemeSwitch.vue')['default'] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createSSRApp } from 'vue' 2 | 3 | import { Locale } from 'nutui-uniapp/locale' 4 | import App from './App.vue' 5 | import 'uno.css' 6 | import './main.scss' 7 | import { setupStore } from './store' 8 | import './styles/app.scss' 9 | import '@nutui/touch-emulator' 10 | 11 | Locale.merge({ 12 | confirm: '确实', 13 | }) 14 | 15 | export function createApp() { 16 | const app = createSSRApp(App) 17 | setupStore(app) 18 | return { 19 | app, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/nutui/components/tabpane/index.scss: -------------------------------------------------------------------------------- 1 | @import '../tabs/index'; 2 | 3 | .nut-theme-dark { 4 | .nut-tab-pane { 5 | background: $dark-background2; 6 | } 7 | } 8 | 9 | .nut-tab-pane { 10 | box-sizing: border-box; 11 | display: block; 12 | flex-shrink: 0; 13 | width: 100%; 14 | height: 100%; 15 | padding: 24px 20px; 16 | overflow: auto; 17 | word-break: break-all; 18 | background-color: #fff; 19 | 20 | &.inactive { 21 | height: 0; 22 | overflow: visible; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/nutui/components/giftbox/giftbox.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const giftboxProps = { 4 | initPrize: { 5 | type: Boolean, 6 | default: true, 7 | }, 8 | } 9 | 10 | export type GiftBoxProps = ExtractPropTypes 11 | 12 | export const giftboxEmits = { 13 | startTurns: () => true, 14 | endTurns: () => true, 15 | } 16 | 17 | export type GiftBoxEmits = typeof giftboxEmits 18 | 19 | export interface GiftBoxInst { 20 | init: () => void 21 | } 22 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | release: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | fetch-depth: 0 18 | 19 | - uses: actions/setup-node@v3 20 | with: 21 | node-version: 18.x 22 | 23 | - run: npx changelogithub 24 | env: 25 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | stats.html 10 | 11 | node_modules 12 | uni_modules/dist 13 | dist 14 | dev-dist 15 | locale 16 | cache 17 | *.local 18 | dist.zip 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | .DS_Store 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw? 30 | .stylelintcache 31 | example/src/components.d.ts 32 | example/src/pages.json 33 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | // https://vitepress.dev/guide/custom-theme 2 | import Theme from 'vitepress/theme' 3 | import Layout from '../components/Layout.vue' 4 | import ReloadPrompt from '../components/ReloadPrompt.vue' 5 | import './style.css' 6 | import 'uno.css' 7 | 8 | export default { 9 | ...Theme, 10 | Layout() { 11 | return h(Layout, null, { 12 | 'layout-bottom': () => h(ReloadPrompt), 13 | }) 14 | }, 15 | // enhanceApp({ app, router, siteData }) { 16 | // // ... 17 | // }, 18 | } 19 | -------------------------------------------------------------------------------- /packages/nutui/components/popover/type.ts: -------------------------------------------------------------------------------- 1 | export type PopoverTheme = 'light' | 'dark' 2 | 3 | export type PopoverLocation = 4 | | 'bottom' 5 | | 'top' 6 | | 'left' 7 | | 'right' 8 | | 'top-start' 9 | | 'top-end' 10 | | 'bottom-start' 11 | | 'bottom-end' 12 | | 'left-start' 13 | | 'left-end' 14 | | 'right-start' 15 | | 'right-end' 16 | 17 | export interface PopoverList { 18 | name: string 19 | icon?: string 20 | disabled?: boolean 21 | className?: any 22 | [key: PropertyKey]: any 23 | } 24 | -------------------------------------------------------------------------------- /docs/components/template.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Template 模板 3 | aside: false 4 | --- 5 | 6 | # 模板 7 | 8 | ## 基础用法 9 | 10 | ```html 11 | 12 | ``` 13 | 14 | ## API 15 | 16 | ### Props 17 | 18 | | 参数 | 说明 | 类型 | 默认值 | 19 | | --- | --- | --- | --- | 20 | | size | 可选值为 `mini` `small` `normal'` `large` | `string` | `normal` | 21 | 22 | ### Events 23 | 24 | | 事件名 | 说明 | 回调参数 | 25 | | --- | --- | --- | 26 | | click | 点击时触发 | `event: MouseEvent`| 27 | 28 | ### Slots 29 | 30 | | 名称 | 说明 | 31 | | --- | --- | 32 | | default | 自定义内容 | 33 | -------------------------------------------------------------------------------- /packages/nutui/components/notify/type.ts: -------------------------------------------------------------------------------- 1 | import type { Position } from '../_constants/types' 2 | 3 | export type NotifyType = 'primary' | 'success' | 'danger' | 'warning' 4 | 5 | export interface NotifyOptions { 6 | type?: NotifyType 7 | msg: string 8 | customColor?: string 9 | background?: string 10 | duration?: number 11 | position?: Position 12 | safeAreaInsetTop?: boolean 13 | } 14 | 15 | export interface NotifyInst { 16 | showNotify: (options: NotifyOptions) => void 17 | hideNotify: () => void 18 | } 19 | -------------------------------------------------------------------------------- /packages/nutui/components/sidenavbaritem/sidenavbaritem.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const sidenavbaritemProps = { 4 | title: { 5 | type: String, 6 | default: '', 7 | }, 8 | ikey: { 9 | type: String, 10 | default: '', 11 | }, 12 | } 13 | 14 | export type SideNavbaritemProps = ExtractPropTypes 15 | 16 | export const sidenavbaritemEmits = { 17 | click: () => true, 18 | } 19 | 20 | export type SideNavbaritemEmits = typeof sidenavbaritemEmits 21 | -------------------------------------------------------------------------------- /packages/nutui/components/list/index.scss: -------------------------------------------------------------------------------- 1 | .nut-list { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | overflow: scroll; 6 | -webkit-overflow-scrolling: touch; 7 | 8 | &-phantom { 9 | position: absolute; 10 | top: 0; 11 | right: 0; 12 | left: 0; 13 | z-index: -1; 14 | } 15 | 16 | &-container { 17 | position: absolute; 18 | top: 0; 19 | right: 0; 20 | left: 0; 21 | } 22 | 23 | &-item { 24 | margin: $list-item-margin; 25 | overflow: hidden; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/nutui/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from 'unbuild' 2 | 3 | export default defineBuildConfig({ 4 | entries: [ 5 | { 6 | builder: 'rollup', 7 | input: './src/index', 8 | outDir: './dist', 9 | }, 10 | { 11 | builder: 'mkdist', 12 | input: './_locale', 13 | outDir: './locale', 14 | }, 15 | ], 16 | declaration: true, 17 | clean: true, 18 | rollup: { 19 | emitCJS: true, 20 | }, 21 | externals: ['vue', '@uni-helper/vite-plugin-uni-components'], 22 | }) 23 | -------------------------------------------------------------------------------- /packages/nutui/components/timepannel/timepannel.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const timepannelProps = { 4 | name: { 5 | type: String, 6 | default: '', 7 | }, 8 | pannelKey: { 9 | type: [Number, String], 10 | default: 0, 11 | }, 12 | } 13 | 14 | export type TimePannelProps = ExtractPropTypes 15 | 16 | export const timepannelEmits = { 17 | change: (pannelKey: number | string) => true, 18 | } 19 | 20 | export type TimePannelEmits = typeof timepannelEmits 21 | -------------------------------------------------------------------------------- /packages/nutui/components/col/index.scss: -------------------------------------------------------------------------------- 1 | .nut-col { 2 | box-sizing: border-box; 3 | float: left; 4 | word-break: break-all; 5 | 6 | &-gutter { 7 | &:last-child { 8 | padding-right: 0 !important; 9 | } 10 | 11 | &:first-child { 12 | padding-left: 0 !important; 13 | } 14 | } 15 | } 16 | 17 | @for $i from 1 through 24 { 18 | .nut-col-offset-#{$i} { 19 | margin-left: calc((100 / 24) * #{$i} * 1%); 20 | } 21 | 22 | .nut-col-#{$i} { 23 | width: calc((100 / 24) * #{$i} * 1%); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nutui-uniapp/docs", 3 | "type": "module", 4 | "version": "0.3.1", 5 | "private": true, 6 | "description": "NutUI for uniapp docs", 7 | "keywords": [ 8 | "nutui", 9 | "docs" 10 | ], 11 | "scripts": { 12 | "dev": "vitepress dev --port 9999", 13 | "build": "vitepress build", 14 | "serve": "vitepress serve --port 6173" 15 | }, 16 | "dependencies": { 17 | "nutui-uniapp": "workspace:^" 18 | }, 19 | "devDependencies": { 20 | "@vite-pwa/vitepress": "^0.2.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/nutui/components/swipe/index.scss: -------------------------------------------------------------------------------- 1 | .nut-swipe { 2 | position: relative; 3 | display: block; 4 | cursor: grab; 5 | transition: all 0.3s cubic-bezier(0.19, 1, 0.22, 1); 6 | 7 | &__left, 8 | &__right { 9 | position: absolute; 10 | top: 0; 11 | height: 100%; 12 | } 13 | 14 | &__left { 15 | left: 0; 16 | transform: translate3d(-100%, 0, 0); 17 | } 18 | 19 | &__right { 20 | right: 0; 21 | transform: translate3d(100%, 0, 0); 22 | } 23 | 24 | &__content { 25 | display: inherit; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/nutui/components/empty/empty.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export type EmptyImage = 'empty' | 'error' | 'network' | string 4 | 5 | export const emptyProps = { 6 | image: { 7 | type: String as PropType, 8 | default: 'empty', // 默认empty 9 | }, 10 | imageSize: { 11 | type: [Number, String], // 图片大小,正方形 12 | default: '', 13 | }, 14 | description: { 15 | type: String, // 文字区 16 | default: '', 17 | }, 18 | } 19 | 20 | export type EmptyProps = ExtractPropTypes 21 | -------------------------------------------------------------------------------- /packages/nutui/components/radio/radio.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export const radioProps = { 4 | disabled: { 5 | type: Boolean, 6 | default: false, 7 | }, 8 | shape: { 9 | type: String as PropType<'round' | 'button'>, 10 | default: 'round', // button 11 | }, 12 | label: { 13 | type: [String, Number, Boolean], 14 | default: '', 15 | }, 16 | iconSize: { 17 | type: [String, Number], 18 | default: '', 19 | }, 20 | } 21 | 22 | export type RadioProps = ExtractPropTypes 23 | -------------------------------------------------------------------------------- /packages/nutui/components/row/row.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const rowProps = { 4 | type: { 5 | type: String, 6 | default: '', 7 | }, 8 | gutter: { 9 | type: [String, Number], 10 | default: '', 11 | }, 12 | justify: { 13 | type: String, 14 | default: 'start', 15 | }, 16 | align: { 17 | type: String, 18 | default: 'flex-start', 19 | }, 20 | flexWrap: { 21 | type: String, 22 | default: 'nowrap', 23 | }, 24 | } 25 | 26 | export type RowProps = ExtractPropTypes 27 | -------------------------------------------------------------------------------- /packages/nutui/styles/mixins/text-ellipsis.scss: -------------------------------------------------------------------------------- 1 | @mixin text-ellipsis() { 2 | overflow: hidden; 3 | text-overflow: ellipsis; 4 | white-space: nowrap; 5 | } 6 | 7 | // 单行超长省略号 8 | @mixin oneline-ellipsis($width: 100%) { 9 | width: $width; 10 | overflow: hidden; 11 | text-overflow: ellipsis; 12 | white-space: nowrap; 13 | } 14 | 15 | // 多行超长省略号 16 | @mixin moreline-ellipsis($line: 2, $width: 100%) { 17 | display: -webkit-box; 18 | -webkit-box-orient: vertical; 19 | -webkit-line-clamp: $line; 20 | overflow: hidden; 21 | word-break: break-all; 22 | } 23 | -------------------------------------------------------------------------------- /docs/guide/faq.md: -------------------------------------------------------------------------------- 1 | # 常见问题 2 | 3 | 这里列举了一些已知问题和暂时的解决方案 4 | 5 | ::: details 使用hbx创建的项目,无法正常使用 popup组件 6 | 临时的解决方案是同时在模板中引入 overlay组件,即可正常使用popup组件。 7 | 建议使用 vite cli创建项目,不会有这些奇怪的问题 8 | ::: 9 | 10 | ::: details 无法自定义组件的class和 style 11 | uniapp在小程序环境组件的 class 和 style 不会被成功编译,如果你想自定义某些组件的 class 或 style,请传递props customClass和customStyle,目前不是每个组件都支持,后续会考虑支持到每个组件 12 | ::: 13 | 14 | ::: details cli样式引入无效 15 | 请详细参考文档 [快速开始](/guide/quick-start) 16 | ::: 17 | 18 | ::: details 某些组件在小程序有一些问题,仅支持 H5 19 | 如 tour,signature等这些在文档中有标注 H5 的组件,代表仅支持 H5 20 | ::: 21 | -------------------------------------------------------------------------------- /packages/nutui/components/signature/index.scss: -------------------------------------------------------------------------------- 1 | @import '../button/index'; 2 | /* stylelint-disable selector-class-pattern */ 3 | 4 | .nut-signature { 5 | .nut-signature-inner { 6 | display: flex; 7 | align-items: center; 8 | justify-content: center; 9 | height: 8rem; 10 | margin-bottom: 1rem; 11 | border: 1px solid #dadada; 12 | } 13 | 14 | .spcanvas_WEAPP { 15 | width: 100%; 16 | height: 100%; 17 | 18 | .spcanvas { 19 | width: 100%; 20 | } 21 | } 22 | 23 | .nut-signature-btn { 24 | margin-right: 15px; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/nutui/components/steps/steps.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const stepsProps = { 4 | direction: { 5 | type: String, 6 | default: 'horizontal', 7 | }, 8 | current: { 9 | type: [String, Number], 10 | default: '0', 11 | }, 12 | progressDot: { 13 | type: Boolean, 14 | default: false, 15 | }, 16 | } 17 | 18 | export type StepsProps = ExtractPropTypes 19 | 20 | export const stepsEmits = { 21 | clickStep: (val: number) => true, 22 | } 23 | 24 | export type StepsEmits = typeof stepsEmits 25 | -------------------------------------------------------------------------------- /packages/nutui/components/tabbaritem/tabbaritem.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { badgeProps } from '../badge' 3 | 4 | export const tabbaritemProps = { 5 | ...badgeProps, 6 | tabTitle: { 7 | // 标签页的标题 8 | type: String, 9 | default: '', 10 | }, 11 | name: { 12 | type: String, 13 | }, 14 | icon: { 15 | // 标签页显示的icon 16 | type: String, 17 | }, 18 | href: { 19 | // 标签页的跳转链接 20 | type: String, 21 | default: '', 22 | }, 23 | } 24 | 25 | export type TabBarItemProps = ExtractPropTypes 26 | -------------------------------------------------------------------------------- /example/src/components/ThemeSwitch.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /packages/nutui/components/sku/index.scss: -------------------------------------------------------------------------------- 1 | @import '../price/index'; 2 | @import '../inputnumber/index'; 3 | @import '../popup/index'; 4 | 5 | .nut-theme-dark { 6 | .nut-sku { 7 | background: $dark-background; 8 | } 9 | } 10 | 11 | .nut-sku { 12 | display: flex; 13 | flex-direction: column; 14 | height: 100%; 15 | padding: 0; 16 | background: $white; 17 | 18 | &-content { 19 | flex: 1; 20 | padding: 0 18px; 21 | margin-top: 24px; 22 | overflow-x: hidden; 23 | overflow-y: auto; 24 | 25 | &::-webkit-scrollbar { 26 | display: none; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/nutui/components/subsidenavbar/subsidenavbar.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const subsidenavbarProps = { 4 | title: { 5 | type: String, 6 | default: '', 7 | }, 8 | ikey: { 9 | type: [String, Number], 10 | default: '', 11 | }, 12 | open: { 13 | type: Boolean, 14 | default: true, 15 | }, 16 | } 17 | 18 | export type SubSidenavbarProps = ExtractPropTypes 19 | 20 | export const subsidenavbarEmits = { 21 | titleClick: () => true, 22 | } 23 | 24 | export type SubSidenavbarEmits = typeof subsidenavbarEmits 25 | -------------------------------------------------------------------------------- /packages/nutui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "types": [ 5 | "@dcloudio/types", 6 | "@uni-helper/uni-app-types" 7 | ] 8 | }, 9 | "include": [ 10 | "**/*.ts", 11 | "**/*.d.ts", 12 | "**/*.vue", 13 | "**/*.tsx" 14 | ], 15 | "exclude": [ 16 | "**/dist/**", 17 | "**/locale/**" 18 | ], 19 | "vueCompilerOptions": { 20 | "experimentalRuntimeMode": "runtime-uni-app", 21 | "nativeTags": [ 22 | "block", 23 | "component", 24 | "template", 25 | "slot" 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/nutui/components/drag/drag.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { commonProps } from '../_utils' 3 | 4 | export const dragProps = { 5 | ...commonProps, 6 | attract: { 7 | type: Boolean, 8 | default: false, 9 | }, 10 | direction: { 11 | type: String, 12 | default: 'all', 13 | }, 14 | boundary: { 15 | type: Object, 16 | default: () => { 17 | return { 18 | top: 0, 19 | left: 0, 20 | right: 0, 21 | bottom: 0, 22 | } 23 | }, 24 | }, 25 | } 26 | 27 | export type DragProps = ExtractPropTypes 28 | -------------------------------------------------------------------------------- /packages/nutui/components/form/form.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import type { ErrorMessage } from './types' 3 | 4 | export const FORM_KEY = Symbol('Form') 5 | 6 | export const formProps = { 7 | modelValue: { 8 | type: Object, 9 | default: {}, 10 | }, 11 | rules: { 12 | type: Object as PropType, 13 | default: {}, 14 | }, 15 | } 16 | 17 | export type FormProps = ExtractPropTypes 18 | 19 | export const formEmits = { 20 | validate: (msg: ErrorMessage) => msg, 21 | } 22 | 23 | export type FormEmits = typeof formEmits 24 | -------------------------------------------------------------------------------- /packages/nutui/components/invoice/invoice.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const invoiceProps = { 4 | data: { 5 | type: Array, 6 | default: () => [], 7 | }, 8 | formValue: { 9 | type: Object, 10 | default: {}, 11 | }, 12 | submit: { 13 | type: Boolean, 14 | default: true, 15 | }, 16 | } 17 | 18 | export type InvoiceProps = ExtractPropTypes 19 | 20 | export const invoiceEmits = { 21 | onSubmit: (valid: any, errors: any) => true, 22 | scrollBottom: () => true, 23 | 24 | } 25 | 26 | export type InvoiceEmits = typeof invoiceEmits 27 | -------------------------------------------------------------------------------- /packages/nutui/components/shakedice/shakedice.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const shakediceProps = { 4 | time: { 5 | type: Number, 6 | default: 1, 7 | }, 8 | speed: { 9 | type: Number, 10 | default: 3000, 11 | }, 12 | id: { 13 | type: Number, 14 | default: 4, 15 | }, 16 | } 17 | 18 | export type ShakeDiceProps = ExtractPropTypes 19 | 20 | export const shakediceEmits = { 21 | end: () => true, 22 | } 23 | 24 | export type ShakeDiceEmits = typeof shakediceEmits 25 | export interface ShakeDiceInst { 26 | shake: () => true 27 | } 28 | -------------------------------------------------------------------------------- /docs/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import AutoImport from 'unplugin-auto-import/vite' 3 | import UnoCSS from 'unocss/vite' 4 | 5 | export default defineConfig({ 6 | plugins: [ 7 | UnoCSS(), 8 | AutoImport({ 9 | imports: ['vue'], 10 | vueTemplate: true, 11 | }), 12 | { 13 | name: 'vitepress-layout-slots-fix', 14 | enforce: 'pre', 15 | transform(code, id) { 16 | if (id.includes('Layout.vue') && !id.endsWith('.css')) 17 | return code.replace('', '\n') 18 | }, 19 | }, 20 | ], 21 | }) 22 | -------------------------------------------------------------------------------- /example/src/pages/demo/bingo/hiteggs/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 基础用法 23 | 24 | 25 | 26 | 27 | 28 | 29 | { 30 | "style": { 31 | "navigationBarTitleText": "HitEggs" 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /packages/nutui/components/tabpane/tabpane.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { commonProps } from '../_utils' 3 | 4 | export const tabpaneProps = { 5 | ...commonProps, 6 | title: { 7 | type: [String, Number], 8 | default: '', 9 | }, 10 | paneKey: { 11 | type: [String, Number], 12 | default: '', 13 | }, 14 | disabled: { 15 | type: Boolean, 16 | default: false, 17 | }, 18 | } 19 | 20 | export type TabPaneProps = ExtractPropTypes 21 | 22 | export const tabpaneEmits = { 23 | click: () => true, 24 | 25 | } 26 | 27 | export type TabPaneEmits = typeof tabpaneEmits 28 | -------------------------------------------------------------------------------- /packages/nutui/components/transition/types.ts: -------------------------------------------------------------------------------- 1 | import type { defaultAnimations } from './use-transition' 2 | 3 | export type TransitionName = keyof typeof defaultAnimations 4 | 5 | export interface NutAnimation { 6 | enter: string 7 | leave: string 8 | } 9 | 10 | export type NutAnimationName = 'fade' | 'fade-up' | 'fade-down' | 'fade-left' | 'fade-right' | 'slide-up' | 'slide-down' | 'slide-left' | 'slide-right' | 'zoom' | 'none' 11 | export type NutAnimationtimingFunction = 'linear' | 'ease' | 'ease-in' | 'ease-in-out' | 'ease-out' | 'step-start' | 'step-end' 12 | export interface NutAnimations { 13 | [key: string]: NutAnimation 14 | } 15 | -------------------------------------------------------------------------------- /packages/nutui/components/_hooks/useLockScroll.ts: -------------------------------------------------------------------------------- 1 | let count = 0 2 | 3 | const CLSNAME = 'nut-overflow-hidden' 4 | 5 | export function useLockScroll(isLock: () => boolean) { 6 | const lock = () => { 7 | if (isLock()) { 8 | try { 9 | !count && document.body.classList.add(CLSNAME) 10 | count++ 11 | } 12 | catch (error) {} 13 | } 14 | } 15 | 16 | const unlock = () => { 17 | if (isLock() && count) { 18 | try { 19 | count-- 20 | !count && document.body.classList.remove(CLSNAME) 21 | } 22 | catch (error) {} 23 | } 24 | } 25 | 26 | return [lock, unlock] 27 | } 28 | -------------------------------------------------------------------------------- /packages/nutui/components/sidenavbaritem/index.scss: -------------------------------------------------------------------------------- 1 | .nut-theme-dark { 2 | .nut-side-navbar-item { 3 | background-color: $dark-background2; 4 | 5 | &__title { 6 | color: $dark-color; 7 | background-color: $dark-background2; 8 | } 9 | } 10 | } 11 | 12 | .nut-side-navbar-item { 13 | display: block; 14 | height: $sidenavbar-item-height; 15 | font-size: $sidenavbar-item-font-size; 16 | line-height: $sidenavbar-item-line-height; 17 | background-color: $sidenavbar-item-title-bg-color; 18 | 19 | &__title { 20 | color: $sidenavbar-item-title-color; 21 | background-color: $sidenavbar-item-title-bg-color; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/nutui/components/griditem/griditem.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const gridItemProps = { 4 | text: { 5 | type: String, 6 | }, 7 | // router 8 | to: { 9 | type: [String, Object], 10 | }, 11 | // #ifdef H5 12 | url: { 13 | type: String, 14 | default: '', 15 | }, 16 | // #endif 17 | replace: { 18 | type: Boolean, 19 | default: false, 20 | }, 21 | } 22 | 23 | export type GridItemProps = ExtractPropTypes 24 | 25 | export const gridItemEmits = { 26 | click: (evt: Event) => evt instanceof Object, 27 | } 28 | 29 | export type GridItemEmits = typeof gridItemEmits 30 | -------------------------------------------------------------------------------- /packages/nutui/_locale/README.md: -------------------------------------------------------------------------------- 1 | # nutui 语言包 2 | 3 | 目前支持的语言: 4 | 5 | | 语言 | 文件名 | 版本 | 6 | |--------------|--------|-----------| 7 | | 英语 | en-US | | 8 | | 印度尼西亚语 | id-ID | | 9 | | 泰语 | th-TH | 等待 PR | 10 | | 简体中文 | zh-CN | | 11 | | 繁體中文 | zh-TW | | 12 | 13 | > 在 [这里](https://github.com/jdf2e/nutui/tree/v4/src/packages/locale/lang) 查看所有的语言包源文件。 14 | 15 | ## 常见问题 16 | 17 | ### 找不到所需的语言包? 18 | 19 | 如果上方列表中没有你需要的语言,欢迎给我们提 Pull Request 来增加新的语言包。改动内容可以参考 [语言包](https://github.com/jdf2e/nutui/tree/v4/src/packages/locale/lang) 语言包 的 PR 20 | 21 | ### 业务代码如何实现国际化? 22 | 23 | 可以使用 [vue-i18n](https://github.com/kazupon/vue-i18n) 来实现。 24 | -------------------------------------------------------------------------------- /packages/nutui/components/divider/divider.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { commonProps } from '../_utils' 3 | 4 | export const dividerProps = { 5 | ...commonProps, 6 | contentPosition: { 7 | type: String as PropType<'left' | 'right' | 'center'>, 8 | default: 'center', 9 | }, 10 | dashed: { 11 | type: Boolean, 12 | default: false, 13 | }, 14 | hairline: { 15 | type: Boolean, 16 | default: true, 17 | }, 18 | direction: { 19 | type: String as PropType<'vertical' | 'horizontal'>, 20 | default: 'horizontal', 21 | }, 22 | } 23 | 24 | export type DividerProps = ExtractPropTypes 25 | -------------------------------------------------------------------------------- /packages/nutui/components/indicator/indicator.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export type IndicatorAlign = 'left' | 'center' | 'right' 4 | 5 | export const indicatorProps = { 6 | size: { 7 | type: Number, 8 | default: 3, 9 | }, 10 | current: { 11 | type: Number, 12 | default: 1, 13 | }, 14 | block: { 15 | type: Boolean, 16 | default: false, 17 | }, 18 | align: { 19 | type: String as PropType, 20 | default: 'center', 21 | }, 22 | fillZero: { 23 | type: Boolean, 24 | default: true, 25 | }, 26 | } 27 | 28 | export type IndicatorProps = ExtractPropTypes 29 | -------------------------------------------------------------------------------- /packages/nutui/components/uploader/type.ts: -------------------------------------------------------------------------------- 1 | export type SizeType = 'original' | 'compressed' 2 | export type SourceType = 'album' | 'camera' 3 | export type AcceptType = 'image' | 'media' | 'video' | 'all' 4 | export type MediaType = 'image' | 'video' | 'mix' 5 | export type FileType = 'image' | 'video' | 'audio' 6 | export type FileItemStatus = 'ready' | 'uploading' | 'success' | 'error' 7 | export interface FileItem { 8 | status: FileItemStatus 9 | 10 | message: string 11 | 12 | uid?: string 13 | 14 | name: string 15 | 16 | url?: string 17 | 18 | type?: FileType 19 | 20 | path?: string 21 | 22 | percentage?: string | number 23 | 24 | formData?: any 25 | } 26 | -------------------------------------------------------------------------------- /packages/nutui/components/collapse/collapse.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const collapseProps = { 4 | modelValue: { 5 | type: [String, Number, Array], 6 | default: '', 7 | }, 8 | accordion: { 9 | type: Boolean, 10 | default: false, 11 | }, 12 | } 13 | 14 | export type CollapseProps = ExtractPropTypes 15 | 16 | export const collapseEmits = { 17 | 'change': (val: string | number | (string | number)[], name: string | number, status: boolean) => true, 18 | 'update:modelValue': (val: string | number | (string | number)[]) => true, 19 | } 20 | 21 | export type CollapseEmits = typeof collapseEmits 22 | -------------------------------------------------------------------------------- /packages/nutui/components/dialog/type.ts: -------------------------------------------------------------------------------- 1 | import type { NutAnimationName } from '../transition' 2 | import type { FooterDirection, TextAlign } from './dialog' 3 | 4 | export interface DialogOptions { 5 | title?: string 6 | content?: string 7 | noFooter?: boolean 8 | noOkBtn?: boolean 9 | noCancelBtn?: boolean 10 | cancelText?: string 11 | okText?: string 12 | textAlign?: TextAlign 13 | footerDirection?: FooterDirection 14 | transition?: NutAnimationName 15 | closeOnClickOverlay?: boolean 16 | okAutoClose?: boolean 17 | } 18 | 19 | export interface DialogInst { 20 | showDialog: (options: DialogOptions) => void 21 | onOk: () => void 22 | onCancel: () => void 23 | } 24 | -------------------------------------------------------------------------------- /packages/nutui/styles/mixins/make-animation.scss: -------------------------------------------------------------------------------- 1 | @mixin make-animation( 2 | $keyframeName, 3 | $timingFun: $animation-timing-fun, 4 | $duration: $animation-duration 5 | ) { 6 | .#{$keyframeName}-enter-active, 7 | .#{$keyframeName}In, 8 | .#{$keyframeName}-leave-active, 9 | .#{$keyframeName}Out { 10 | animation-duration: $duration; 11 | animation-fill-mode: both; 12 | animation-timing-function: $timingFun; 13 | } 14 | 15 | .#{$keyframeName}-enter-active, 16 | .#{$keyframeName}In { 17 | animation-name: #{$keyframeName}In; 18 | } 19 | 20 | .#{$keyframeName}-leave-active, 21 | .#{$keyframeName}Out { 22 | animation-name: #{$keyframeName}Out; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/nutui/components/category/category.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { isNumber } from '../_utils' 3 | 4 | export interface CategoryType { 5 | catName?: string 6 | [key: string]: any 7 | } 8 | 9 | export const categoryProps = { 10 | // 分类模式 11 | type: { 12 | type: String, 13 | default: 'classify', 14 | }, 15 | 16 | // 左侧导航栏 17 | category: { 18 | type: Array as PropType, 19 | default: () => [], 20 | }, 21 | } 22 | 23 | export type CategoryProps = ExtractPropTypes 24 | 25 | export const categoryEmits = { 26 | change: (index: number) => isNumber(index), 27 | } 28 | 29 | export type CategoryEmits = typeof categoryEmits 30 | -------------------------------------------------------------------------------- /packages/nutui/components/pickercolumn/types.ts: -------------------------------------------------------------------------------- 1 | export interface PickerOption { 2 | [key: PropertyKey]: any 3 | text: string | number 4 | value: string | number 5 | disabled?: string 6 | children?: PickerOption[] 7 | className?: string | number 8 | } 9 | 10 | export interface PickerColumnOption { 11 | text: string 12 | value: string 13 | disabled: string 14 | children: PickerOption[] 15 | className: string 16 | } 17 | 18 | export interface TouchParams { 19 | startY: number 20 | endY: number 21 | startTime: number 22 | endTime: number 23 | lastY: number 24 | lastTime: number 25 | } 26 | 27 | export interface PickerFieldNames { 28 | text?: string 29 | value?: string 30 | children?: string 31 | } 32 | -------------------------------------------------------------------------------- /packages/nutui/components/backtop/index.scss: -------------------------------------------------------------------------------- 1 | .nut-theme-dark { 2 | .nut-backtop { 3 | &.show { 4 | color: $dark-color; 5 | background: $dark-background; 6 | border: 1px solid $dark-background; 7 | } 8 | } 9 | } 10 | 11 | .nut-backtop { 12 | position: fixed; 13 | display: none; 14 | 15 | &.show { 16 | display: flex; 17 | align-items: center; 18 | justify-content: center; 19 | width: 40px; 20 | height: 40px; 21 | background: $white; 22 | border: 1px solid $backtop-border-color; 23 | border-radius: 50%; 24 | } 25 | 26 | &.show :active { 27 | background: rgb(0 0 0 / 10%); 28 | } 29 | 30 | &-main { 31 | transition: all 0.2s ease-in-out; 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /packages/nutui/components/rate/index.scss: -------------------------------------------------------------------------------- 1 | .nut-rate { 2 | display: inline-flex; 3 | 4 | &-item { 5 | position: relative; 6 | display: flex; 7 | flex-shrink: 0; 8 | margin-right: 14px; 9 | 10 | &:last-child { 11 | margin-right: 0; 12 | } 13 | 14 | &__icon { 15 | flex-shrink: 0; 16 | color: $rate-icon-color; 17 | cursor: pointer; 18 | 19 | &--disabled { 20 | color: $rate-icon-void-color; 21 | } 22 | 23 | &--full { 24 | display: flex; 25 | } 26 | 27 | &--half { 28 | position: absolute; 29 | top: 0; 30 | left: 0; 31 | display: flex; 32 | width: 50%; 33 | overflow: hidden; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/nutui/components/toast/types.ts: -------------------------------------------------------------------------------- 1 | export type ToastType = 'success' | 'loading' | 'fail' | 'warn' | 'text' 2 | 3 | export interface ToastOptions { 4 | msg?: string 5 | duration?: number 6 | type?: ToastType 7 | title?: string 8 | iconSize?: string | number 9 | icon?: string 10 | bgColor?: string 11 | size?: string | number 12 | bottom?: string 13 | } 14 | 15 | export interface ToastInst { 16 | showToast: { 17 | text(msg: string, options?: ToastOptions): void 18 | success(msg: string, options?: ToastOptions): void 19 | fail(msg: string, options?: ToastOptions): void 20 | warn(msg: string, options?: ToastOptions): void 21 | loading(msg: string, options?: ToastOptions): void 22 | } 23 | hideToast: () => void 24 | } 25 | -------------------------------------------------------------------------------- /packages/nutui/components/avatar/avatar.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { commonProps } from '../_utils' 3 | 4 | export type AvatarSize = 'large' | 'normal' | 'small' 5 | export type AvatarShape = 'round' | 'square' 6 | 7 | export const avatarProps = { 8 | ...commonProps, 9 | size: { 10 | type: [String, Number] as PropType, 11 | default: 'normal', 12 | }, 13 | shape: { 14 | type: String as PropType, 15 | default: 'round', 16 | }, 17 | bgColor: { 18 | type: String, 19 | default: '#eee', 20 | }, 21 | customColor: { 22 | type: String, 23 | default: '#666', 24 | }, 25 | } 26 | 27 | export type AvatarProps = ExtractPropTypes 28 | -------------------------------------------------------------------------------- /packages/nutui/components/radiogroup/radiogroup.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export const radiogroupProps = { 4 | modelValue: { 5 | type: [Number, String, Boolean], 6 | default: '', 7 | }, 8 | direction: { 9 | type: String as PropType<'vertical' | 'horizontal'>, 10 | default: 'vertical', // horizontal 11 | }, 12 | textPosition: { 13 | type: String, 14 | default: 'right', 15 | }, 16 | } 17 | 18 | export type RadioGroupProps = ExtractPropTypes 19 | 20 | export const radiogroupEmits = { 21 | 'change': (val: string | number | boolean) => true, 22 | 'update:modelValue': (val: string | boolean | number) => true, 23 | } 24 | 25 | export type RadioGroupEmits = typeof radiogroupEmits 26 | -------------------------------------------------------------------------------- /packages/nutui/components/_utils/raf.ts: -------------------------------------------------------------------------------- 1 | const _window = window as any 2 | 3 | export const inBrowser = typeof window !== 'undefined' 4 | 5 | function requestAniFrame() { 6 | if (typeof _window !== 'undefined') { 7 | return ( 8 | _window.requestAnimationFrame 9 | || _window.webkitRequestAnimationFrame 10 | || function (callback: () => void) { 11 | _window.setTimeout(callback, 1000 / 60) 12 | } 13 | ) 14 | } 15 | else { 16 | return function (callback: () => void) { 17 | setTimeout(callback, 1000 / 60) 18 | } 19 | } 20 | } 21 | 22 | export function cancelRaf(id: number) { 23 | if (inBrowser) 24 | cancelAnimationFrame(id) 25 | 26 | else 27 | clearTimeout(id) 28 | } 29 | 30 | export default requestAniFrame() 31 | -------------------------------------------------------------------------------- /packages/nutui/components/circleprogress/index.scss: -------------------------------------------------------------------------------- 1 | .nut-theme-dark { 2 | .nut-circle-progress{ 3 | .nut-circle-progress__text { 4 | color: $dark-color; 5 | } 6 | } 7 | 8 | } 9 | 10 | .nut-circle-progress { 11 | position: relative; 12 | 13 | &__hover { 14 | stroke: $circleprogress-primary-color; 15 | transition: stroke-dasharray 0.6s ease 0s, stroke 0.6s ease 0s; 16 | } 17 | 18 | &__path { 19 | stroke: $circleprogress-path-color; 20 | } 21 | 22 | &__text { 23 | position: absolute; 24 | top: 50%; 25 | left: 0; 26 | box-sizing: border-box; 27 | width: 100%; 28 | font-size: $circleprogress-text-size; 29 | color: $circleprogress-text-color; 30 | text-align: center; 31 | transform: translateY(-50%); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/nutui/components/_hooks/useRouter.ts: -------------------------------------------------------------------------------- 1 | export type NavigateToOptions = string | UniApp.NavigateToOptions 2 | export type RedirectToOptions = string | UniApp.RedirectToOptions 3 | 4 | export type RouterOptions = UniApp.NavigateToOptions | UniApp.RedirectToOptions 5 | 6 | export function useRouter() { 7 | const push = (options: NavigateToOptions) => { 8 | if (typeof options === 'string') { 9 | uni.navigateTo({ url: options }) 10 | return 11 | } 12 | 13 | uni.navigateTo(options) 14 | } 15 | const replace = (options: RedirectToOptions) => { 16 | if (typeof options === 'string') { 17 | uni.redirectTo({ url: options }) 18 | return 19 | } 20 | 21 | uni.redirectTo(options) 22 | } 23 | 24 | return { 25 | push, 26 | replace, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/issue-labeled.yml: -------------------------------------------------------------------------------- 1 | name: Issue Labeled 2 | 3 | on: 4 | issues: 5 | types: [labeled] 6 | 7 | jobs: 8 | reply-labeled: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: need reproduction 12 | if: github.event.label.name == 'need reproduction' 13 | uses: actions-cool/issues-helper@v3 14 | with: 15 | actions: create-comment 16 | token: ${{ secrets.GITHUB_TOKEN }} 17 | issue-number: ${{ github.event.issue.number }} 18 | body: | 19 | Hello @${{ github.event.issue.user.login }}. Please provide a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) using a GitHub repository or [StackBlitz]. Issues marked with `need reproduction` will be closed if they have no activity within 3 days. 20 | -------------------------------------------------------------------------------- /packages/nutui/components/tabbar/index.scss: -------------------------------------------------------------------------------- 1 | .nut-theme-dark { 2 | .nut-tabbar { 3 | background: $dark-background; 4 | border-color: $dark-background; 5 | } 6 | } 7 | 8 | .nut-tabbar { 9 | box-sizing: content-box; 10 | display: flex; 11 | align-items: center; 12 | width: 100%; 13 | height: $tabbar-height; 14 | background: $white; 15 | border: 0; 16 | border-top: $tabbar-border-top; 17 | border-bottom: $tabbar-border-bottom; 18 | box-shadow: $tabbar-box-shadow; 19 | 20 | &:last-child { 21 | border-right: 0; 22 | } 23 | 24 | &-bottom { 25 | position: fixed; 26 | bottom: 0; 27 | left: 0; 28 | z-index: 888; 29 | } 30 | 31 | &-safebottom { 32 | padding-bottom: constant(safe-area-inset-bottom); 33 | padding-bottom: env(safe-area-inset-bottom); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/nutui/components/guessgift/guessgift.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const guessgiftProps = { 4 | initPrize: { 5 | type: Boolean, 6 | default: true, 7 | }, 8 | turnNumber: { 9 | type: Number, 10 | default: 20, 11 | }, 12 | turnsFrequency: { 13 | type: Number, 14 | default: 500, 15 | }, 16 | raiseHeight: { 17 | type: Number, 18 | default: 50, 19 | }, 20 | prizeIndex: { 21 | type: Number, 22 | default: -1, 23 | }, 24 | } 25 | 26 | export type GuessGiftProps = ExtractPropTypes 27 | 28 | export const guessgiftEmits = { 29 | startTurns: () => true, 30 | endTurns: () => true, 31 | } 32 | 33 | export type GuessGiftEmits = typeof guessgiftEmits 34 | export interface ShakeDiceInst { 35 | shake: () => true 36 | } 37 | -------------------------------------------------------------------------------- /packages/nutui/components/badge/badge.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const badgeProps = { 4 | value: { 5 | type: [String, Number], 6 | }, 7 | max: { 8 | type: Number, 9 | default: 10000, 10 | }, 11 | dot: { 12 | type: Boolean, 13 | default: false, 14 | }, 15 | bubble: { 16 | type: Boolean, 17 | default: false, 18 | }, 19 | badgeHidden: { 20 | type: Boolean, 21 | default: false, 22 | }, 23 | top: { 24 | type: String, 25 | default: '0', 26 | }, 27 | right: { 28 | type: String, 29 | default: '0', 30 | }, 31 | zIndex: { 32 | type: Number, 33 | default: 9, 34 | }, 35 | customColor: { 36 | type: String, 37 | default: '', 38 | }, 39 | } 40 | 41 | export type BadgeProps = ExtractPropTypes 42 | -------------------------------------------------------------------------------- /packages/nutui/components/card/card.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { commonProps } from '../_utils' 3 | 4 | export const cardProps = { 5 | ...commonProps, 6 | imgUrl: { 7 | type: String, 8 | default: '', 9 | }, 10 | title: { 11 | type: String, 12 | default: '', 13 | }, 14 | price: { 15 | type: String, 16 | default: '', 17 | }, 18 | vipPrice: { 19 | type: String, 20 | default: '', 21 | }, 22 | shopDesc: { 23 | type: String, 24 | default: '', 25 | }, 26 | delivery: { 27 | type: String, 28 | default: '', 29 | }, 30 | shopName: { 31 | type: String, 32 | default: '', 33 | }, 34 | isNeedPrice: { 35 | type: Boolean, 36 | default: true, 37 | }, 38 | } 39 | 40 | export type CardProps = ExtractPropTypes 41 | -------------------------------------------------------------------------------- /packages/nutui/components/input/util.ts: -------------------------------------------------------------------------------- 1 | function trimExtraChar(value: string, char: string, regExp: RegExp) { 2 | const index = value.indexOf(char) 3 | 4 | if (index === -1) 5 | return value 6 | 7 | if (char === '-' && index !== 0) 8 | return value.slice(0, index) 9 | 10 | return value.slice(0, index + 1) + value.slice(index).replace(regExp, '') 11 | } 12 | 13 | export function formatNumber(value: string, allowDot = true, allowMinus = true) { 14 | if (allowDot) 15 | value = trimExtraChar(value, '.', /\./g) 16 | 17 | else 18 | value = value.split('.')[0] 19 | 20 | if (allowMinus) 21 | value = trimExtraChar(value, '-', /-/g) 22 | 23 | else 24 | value = value.replace(/-/, '') 25 | 26 | const regExp = allowDot ? /[^-0-9.]/g : /[^-0-9]/g 27 | 28 | return value.replace(regExp, '') 29 | } 30 | -------------------------------------------------------------------------------- /packages/nutui/components/barrage/barrage.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const barrageProps = { 4 | danmu: { 5 | type: Array, 6 | default: () => [], 7 | }, 8 | frequency: { 9 | type: Number, 10 | default: 500, 11 | }, 12 | speeds: { 13 | type: Number, 14 | default: 5000, 15 | }, 16 | rows: { 17 | type: Number, 18 | default: 3, 19 | }, 20 | top: { 21 | type: Number, 22 | default: 10, 23 | }, 24 | loop: { 25 | type: Boolean, 26 | default: true, 27 | }, 28 | } 29 | 30 | export type BarrageProps = ExtractPropTypes 31 | 32 | export const barrageEmits = { 33 | click: () => true, 34 | } 35 | 36 | export type BarrageEmits = typeof barrageEmits 37 | 38 | export interface BarrageInst { 39 | add: (word: string) => void 40 | } 41 | -------------------------------------------------------------------------------- /packages/nutui/components/skuheader/index.scss: -------------------------------------------------------------------------------- 1 | .nut-theme-dark { 2 | .nut-sku { 3 | &-operate { 4 | &-btn { 5 | background: $dark-background2; 6 | } 7 | } 8 | } 9 | } 10 | 11 | .nut-sku-header { 12 | display: flex; 13 | flex-shrink: 0; 14 | height: 100px; 15 | padding: 0 18px; 16 | margin-top: 18px; 17 | 18 | .nut-sku-header-img { 19 | flex-shrink: 0; 20 | width: $sku-product-img-width; 21 | height: $sku-product-img-height; 22 | margin-right: 12px; 23 | border-radius: $sku-product-img-border-radius; 24 | } 25 | 26 | &-right { 27 | display: flex; 28 | flex: 1; 29 | flex-direction: column; 30 | justify-content: flex-end; 31 | 32 | &-extra { 33 | font-size: 12px; 34 | color: $text-color; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /packages/nutui/components/timepannel/index.scss: -------------------------------------------------------------------------------- 1 | .nut-theme-dark { 2 | .nut-time-pannel { 3 | color: $dark-color-gray; 4 | background-color: $dark-background3; 5 | 6 | &--curr { 7 | color: $dark-color; 8 | background-color: $dark-background2; 9 | } 10 | } 11 | } 12 | 13 | .nut-time-pannel { 14 | box-sizing: border-box; 15 | display: flex; 16 | align-items: center; 17 | justify-content: center; 18 | width: $timeselect-timepannel-width; 19 | height: $timeselect-timepannel-height; 20 | padding: $timeselect-timepannel-padding; 21 | font-size: $timeselect-timepannel-font-size; 22 | color: $timeselect-timepannel-text-color; 23 | 24 | &--curr { 25 | font-weight: bold; 26 | color: $timeselect-timepannel-cur-text-color; 27 | background-color: $timeselect-timepannel-cur-bg-color; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/nutui/components/animate/animate.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import type { AnimateAction, AnimateType } from './type' 3 | 4 | export const animateProps = { 5 | type: { 6 | type: String as PropType, 7 | default: '', 8 | }, 9 | show: { 10 | type: Boolean, 11 | default: false, 12 | }, 13 | action: { 14 | type: String as PropType, 15 | default: 'initial', 16 | }, 17 | loop: { 18 | type: Boolean, 19 | default: false, 20 | }, 21 | duration: { 22 | type: [String, Number], 23 | default: 500, 24 | }, 25 | } 26 | 27 | export type AnimateProps = ExtractPropTypes 28 | 29 | export const animateEmits = { 30 | click: (evt: Event) => evt, 31 | animate: () => true, 32 | } 33 | 34 | export type AnimateEmits = typeof animateEmits 35 | -------------------------------------------------------------------------------- /packages/nutui/components/backtop/backtop.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | const { theme } = uni.getSystemInfoSync() 4 | 5 | export const backtopProps = { 6 | height: { 7 | type: String, 8 | default: '100vh', 9 | }, 10 | bottom: { 11 | type: Number, 12 | default: 20, 13 | }, 14 | right: { 15 | type: Number, 16 | default: 10, 17 | }, 18 | zIndex: { 19 | type: Number, 20 | default: 10, 21 | }, 22 | distance: { 23 | type: Number, 24 | default: 200, 25 | }, 26 | customColor: { 27 | type: String, 28 | default: theme === 'dark' ? '#fff' : '#000', 29 | }, 30 | } 31 | 32 | export type BacktopProps = ExtractPropTypes 33 | 34 | export const backtopEmits = { 35 | click: (evt: MouseEvent) => evt, 36 | } 37 | 38 | export type BacktopEmits = typeof backtopEmits 39 | -------------------------------------------------------------------------------- /packages/nutui/components/cascader/types.ts: -------------------------------------------------------------------------------- 1 | export interface CascaderPane { 2 | nodes: CascaderOption[] 3 | selectedNode: CascaderOption | null 4 | } 5 | 6 | export interface CascaderConfig { 7 | value?: string 8 | text?: string 9 | children?: string 10 | } 11 | export interface CascaderTabs { 12 | title: string 13 | paneKey: string 14 | disabled: boolean 15 | } 16 | 17 | export interface CascaderOption { 18 | text?: string 19 | value?: number | string 20 | disabled?: boolean 21 | children?: CascaderOption[] 22 | leaf?: boolean 23 | level?: number 24 | loading?: boolean 25 | 26 | [key: PropertyKey]: any 27 | } 28 | 29 | export type CascaderValue = CascaderOption['value'][] 30 | 31 | export interface convertConfig { 32 | topId?: string | number | null 33 | idKey?: string 34 | pidKey?: string 35 | sortKey?: string 36 | } 37 | -------------------------------------------------------------------------------- /docs/components/feedback/drag.md: -------------------------------------------------------------------------------- 1 | # Drag 拖拽 2 | 3 | ### 介绍 4 | 5 | 实现可拖拽的任意元素 6 | 7 | ### 基础用法 8 | 9 | ```html 10 | 11 | 可点击,可拖拽 12 | 13 | ``` 14 | 15 | ### 限制拖拽方向 16 | 17 | ```html 18 | 19 | 只能在X轴拖动 20 | 21 | ``` 22 | 23 | ### 限制拖拽方向 24 | 25 | ```html 26 | 27 | 只能在Y轴拖动 28 | 29 | ``` 30 | 31 | ## API 32 | 33 | ### Props 34 | 35 | | 参数 | 说明 | 类型 | 默认值 | 36 | | :-------- | :------------------------------------------------ | :------------- | :---------------------------------- | 37 | | direction | 拖拽元素的拖拽方向限制,**x**/**y**/**all** 三选一 | string | `all` | 38 | -------------------------------------------------------------------------------- /packages/nutui/components/table/table.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import type { TableColumnProps } from './types' 3 | 4 | export const tableProps = { 5 | bordered: { 6 | type: Boolean, 7 | default: true, 8 | }, 9 | columns: { 10 | type: Array as PropType, 11 | default: () => { 12 | return [] 13 | }, 14 | }, 15 | data: { 16 | type: Object, 17 | default: () => { 18 | return {} 19 | }, 20 | }, 21 | summary: { 22 | type: Function, 23 | default: null, 24 | }, 25 | striped: { 26 | type: Boolean, 27 | default: false, 28 | }, 29 | } 30 | 31 | export type TableProps = ExtractPropTypes 32 | 33 | export const tableEmits = { 34 | sorter: (val: TableColumnProps) => true, 35 | } 36 | 37 | export type TableEmits = typeof tableEmits 38 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.json", 3 | "compilerOptions": { 4 | "lib": [ 5 | "esnext", 6 | "dom" 7 | ], 8 | "baseUrl": ".", 9 | "paths": { 10 | "@/*": [ 11 | "src/*" 12 | ] 13 | }, 14 | "types": [ 15 | "@dcloudio/types", 16 | "@uni-helper/uni-app-types", 17 | "nutui-uniapp/global.d.ts" 18 | ], 19 | "sourceMap": true 20 | }, 21 | "include": [ 22 | "node_modules/nutui-uniapp/global.d.ts", 23 | "src/**/*.vue", 24 | "src/**/*.ts", 25 | "src/pages/demo/business/category/data.js", 26 | "src/**/*.d.ts", 27 | "src/**/*.tsx", 28 | "src/utils/touchEmulator.js" 29 | ], 30 | "vueCompilerOptions": { 31 | "nativeTags": [ 32 | "block", 33 | "component", 34 | "template", 35 | "slot" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/nutui/components/sticky/sticky.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { commonProps, isH5 } from '../_utils' 3 | 4 | export const stickyProps = { 5 | ...commonProps, 6 | zIndex: { 7 | type: [Number, String], 8 | default: '', 9 | }, 10 | offsetTop: { 11 | type: [Number, String], 12 | default: 0, 13 | }, 14 | customNavHeight: { 15 | type: [String, Number], 16 | // H5端的导航栏属于“自定义”导航栏的范畴,因为它是非原生的,与普通元素一致 17 | default: isH5 ? 44 : 0, 18 | }, 19 | // 是否开启吸顶功能 20 | disabled: { 21 | type: Boolean, 22 | default: false, 23 | }, 24 | // 吸顶区域的背景颜色 25 | bgColor: { 26 | type: String, 27 | default: 'transparent', 28 | }, 29 | // 列表中的索引值 30 | index: { 31 | type: [String, Number], 32 | default: '', 33 | }, 34 | } 35 | 36 | export type StickyProps = ExtractPropTypes 37 | -------------------------------------------------------------------------------- /packages/nutui/components/checkboxgroup/checkboxgroup.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { isArray } from '../_utils' 3 | 4 | export const checkboxgroupProps = { 5 | modelValue: { 6 | type: Array, 7 | default: () => [], 8 | }, 9 | disabled: { 10 | type: Boolean, 11 | default: false, 12 | }, 13 | max: { 14 | type: Number, 15 | default: 0, 16 | }, 17 | } 18 | 19 | export type CheckboxGroupProps = ExtractPropTypes 20 | 21 | export const checkboxgroupEmits = { 22 | 'change': (val: any[]) => { 23 | return { 24 | val, 25 | } 26 | }, 27 | 'update:modelValue': (val: any[]) => isArray(val), 28 | } 29 | 30 | export type CheckboxGroupEmits = typeof checkboxgroupEmits 31 | 32 | export interface CheckBoxInst { 33 | toggleAll: (val: boolean) => void 34 | toggleReverse: () => void 35 | } 36 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | ### Description 15 | 16 | 17 | 18 | ### Linked Issues 19 | 20 | 21 | 22 | ### Additional Context 23 | 24 | -------------------------------------------------------------------------------- /packages/nutui/components/empty/index.scss: -------------------------------------------------------------------------------- 1 | .nut-theme-dark { 2 | .nut-empty { 3 | background: $dark-background; 4 | } 5 | } 6 | 7 | .nut-empty { 8 | box-sizing: border-box; 9 | display: flex; 10 | flex-direction: column; 11 | align-items: center; 12 | justify-content: center; 13 | padding: $empty-padding; 14 | 15 | &__box { 16 | width: $empty-image-size; 17 | height: $empty-image-size; 18 | 19 | .img { 20 | width: 100%; 21 | height: 100%; 22 | } 23 | 24 | // 兼容小程序标签和img-slot 25 | image { 26 | width: 100%; 27 | height: 100%; 28 | } 29 | } 30 | 31 | &__description { 32 | padding: $empty-description-padding; 33 | margin-top: $empty-description-margin-top; 34 | font-size: $empty-description-font-size; 35 | line-height: $empty-description-line-height; 36 | color: $empty-description-color; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/nutui/components/trendarrow/trendarrow.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const trendarrowProps = { 4 | rate: { 5 | type: Number, 6 | default: 0, 7 | }, 8 | digits: { 9 | type: Number, 10 | default: 2, 11 | }, 12 | showSign: { 13 | type: Boolean, 14 | default: false, 15 | }, 16 | showZero: { 17 | type: Boolean, 18 | default: false, 19 | }, 20 | arrowLeft: { 21 | type: Boolean, 22 | default: false, 23 | }, 24 | syncTextColor: { 25 | type: Boolean, 26 | default: true, 27 | }, 28 | textColor: { 29 | type: String, 30 | default: '#333', 31 | }, 32 | riseColor: { 33 | type: String, 34 | default: '#fa2c19', 35 | }, 36 | dropColor: { 37 | type: String, 38 | default: '#64b578', 39 | }, 40 | } 41 | 42 | export type TrendArrowProps = ExtractPropTypes 43 | -------------------------------------------------------------------------------- /packages/nutui/components/_hooks/useStyle.ts: -------------------------------------------------------------------------------- 1 | import { computed, normalizeClass, normalizeStyle } from 'vue' 2 | import { stringifyStyle } from '../_utils' 3 | 4 | export function useStyleContext(props: any, componentName: string) { 5 | const mainClass = computed(() => { 6 | const cls = normalizeClass([props.customClass, { [componentName]: true }]) 7 | 8 | return cls 9 | }) 10 | 11 | const mainStyle = computed(() => { 12 | return stringifyStyle(normalizeStyle(props.customStyle)) 13 | }) 14 | 15 | const getMainClass = (cls: unknown) => { 16 | return normalizeClass([props.customClass, { [componentName]: true }, cls]) 17 | } 18 | 19 | const getMainStyle = (style: unknown) => { 20 | return stringifyStyle(normalizeStyle([props.customStyle, style])) 21 | } 22 | 23 | return { 24 | mainClass, 25 | mainStyle, 26 | getMainClass, 27 | getMainStyle, 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/nutui/components/collapseitem/collapseitem.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const collapseitemProps = { 4 | collapseRef: { 5 | type: Object, 6 | }, 7 | title: { 8 | type: String, 9 | default: '', 10 | }, 11 | value: { 12 | type: String, 13 | default: '', 14 | }, 15 | label: { 16 | type: String, 17 | default: '', 18 | }, 19 | disabled: { 20 | type: Boolean, 21 | default: false, 22 | }, 23 | name: { 24 | type: [Number, String], 25 | default: -1, 26 | required: true, 27 | }, 28 | border: { 29 | type: Boolean, 30 | default: true, 31 | }, 32 | icon: { 33 | type: String, 34 | default: () => 'down-arrow', 35 | }, 36 | rotate: { 37 | type: [String, Number], 38 | default: 180, 39 | }, 40 | } 41 | 42 | export type CollapseItemProps = ExtractPropTypes 43 | -------------------------------------------------------------------------------- /packages/nutui/components/signature/signature.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { commonProps } from '../_utils' 3 | 4 | const { theme } = uni.getSystemInfoSync() 5 | 6 | export const signatureProps = { 7 | ...commonProps, 8 | lineWidth: { 9 | type: Number, 10 | default: 2, 11 | }, 12 | strokeStyle: { 13 | type: String, 14 | default: '#000', 15 | }, 16 | type: { 17 | type: String, 18 | default: 'png', 19 | }, 20 | unSupportTpl: { 21 | type: String, 22 | default: '', 23 | }, 24 | } 25 | 26 | export type SignatureProps = ExtractPropTypes 27 | 28 | export const signatureEmits = { 29 | start: () => true, 30 | end: () => true, 31 | signing: (event: any) => true, 32 | confirm: (_canvas: any, _filePath?: string) => true, 33 | clear: () => true, 34 | } 35 | 36 | export type SignatureEmits = typeof signatureEmits 37 | -------------------------------------------------------------------------------- /packages/nutui/components/loadingpage/index.scss: -------------------------------------------------------------------------------- 1 | .nut-loading-page { 2 | display: flex; 3 | flex: 1; 4 | flex-direction: column; 5 | align-items: center; 6 | justify-content: center; 7 | 8 | &__warpper { 9 | display: flex; 10 | flex-direction: column; 11 | align-items: center; 12 | justify-content: center; 13 | margin-top: -150px; 14 | 15 | /* #ifndef APP-NVUE */ 16 | 17 | font-size: $font-size-4; 18 | color: $text-color; 19 | 20 | /* #endif */ 21 | 22 | 23 | &__loading-icon { 24 | margin-bottom: $loadingpage-icon-margin-bottom; 25 | 26 | &__img { 27 | width: 40px; 28 | height: 40px; 29 | } 30 | } 31 | 32 | &__text { 33 | font-size: $font-size-4; 34 | color: $text-color; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /packages/nutui/components/_utils/interceptor.ts: -------------------------------------------------------------------------------- 1 | import { isPromise } from './is' 2 | 3 | export type Interceptor = (...args: any[]) => Promise | boolean | undefined | void 4 | 5 | export function funInterceptor(interceptor: Interceptor | undefined, { 6 | args = [], 7 | done, 8 | canceled, 9 | }: { 10 | args?: unknown[] 11 | done: (val?: any) => void 12 | canceled?: () => void 13 | }) { 14 | if (interceptor) { 15 | const returnVal = interceptor(null, ...args) 16 | 17 | if (isPromise(returnVal)) { 18 | returnVal 19 | .then((value) => { 20 | if (value) 21 | done(value) 22 | else if (canceled) 23 | canceled() 24 | }) 25 | .catch(() => {}) 26 | } 27 | else if (returnVal) { 28 | done() 29 | } 30 | else if (canceled) { 31 | canceled() 32 | } 33 | } 34 | else { 35 | done() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/nutui/components/addresslist/index.scss: -------------------------------------------------------------------------------- 1 | @import '../button/index'; 2 | @import '../swipe/index'; 3 | 4 | .nut-theme-dark { 5 | .nut-address-list { 6 | &__bottom { 7 | background-color: $dark-background2; 8 | } 9 | } 10 | } 11 | 12 | .nut-address-list { 13 | overflow: hidden; 14 | 15 | &:last-child { 16 | padding-bottom: 84px; 17 | } 18 | 19 | 20 | 21 | 22 | &__bottom { 23 | position: fixed; 24 | right: 0; 25 | bottom: 0; 26 | bottom: constant(safe-area-inset-bottom); 27 | bottom: env(safe-area-inset-bottom); 28 | left: 0; 29 | z-index: 100000; 30 | box-sizing: border-box; 31 | width: 100%; 32 | padding: 12px 18px 24px; 33 | background-color: $addresslist-bg; 34 | } 35 | 36 | .nut-address-list__mask-bottom { 37 | position: fixed; 38 | inset: 0; 39 | z-index: 2000; 40 | background-color: transparent; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/nutui/components/cell/cell.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { commonProps } from '../_utils' 3 | 4 | export const cellProps = { 5 | ...commonProps, 6 | title: { type: String, default: '' }, 7 | subTitle: { type: String, default: '' }, 8 | desc: { type: String, default: '' }, 9 | descTextAlign: { type: String, default: 'right' }, 10 | isLink: { type: Boolean, default: false }, 11 | to: { type: String, default: '' }, 12 | replace: { type: Boolean, default: false }, 13 | roundRadius: { type: [String, Number], default: '' }, 14 | url: { type: String, default: '' }, 15 | center: { type: Boolean, default: false }, 16 | size: { type: String, default: '' }, // large 17 | } 18 | 19 | export type CellProps = ExtractPropTypes 20 | 21 | export const cellEmits = { 22 | click: (event: Event) => event, 23 | } 24 | 25 | export type CellEmits = typeof cellEmits 26 | -------------------------------------------------------------------------------- /packages/nutui/components/icon/icon.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { commonProps } from '../_utils' 3 | 4 | export const iconProps = { 5 | ...commonProps, 6 | popClass: { type: String, default: '' }, 7 | width: { type: [String, Number], default: '' }, 8 | height: { type: [String, Number], default: '' }, 9 | name: { type: String, default: '' }, 10 | size: { type: [String, Number], default: '' }, 11 | classPrefix: { type: String, default: 'nut-icon' }, 12 | fontClassName: { type: String, default: 'nutui-iconfont' }, 13 | customColor: { type: String, default: '' }, 14 | tag: { type: String as PropType, default: 'i' }, 15 | } 16 | 17 | export type IconProps = ExtractPropTypes 18 | 19 | export const iconEmits = { 20 | click: (evt: Event) => evt instanceof Object, 21 | } 22 | 23 | export type IconEmits = typeof iconEmits 24 | -------------------------------------------------------------------------------- /packages/nutui/styles/animation/zoom.scss: -------------------------------------------------------------------------------- 1 | @keyframes nutZoomIn { 2 | 0% { 3 | opacity: 0; 4 | transform: scale3d(0.3, 0.3, 0.3); 5 | } 6 | 7 | 50% { 8 | opacity: 1; 9 | } 10 | } 11 | 12 | @keyframes nutZoomOut { 13 | 0% { 14 | opacity: 1; 15 | } 16 | 17 | 50% { 18 | opacity: 0; 19 | transform: scale3d(0.3, 0.3, 0.3); 20 | } 21 | 22 | 100% { 23 | opacity: 0; 24 | } 25 | } 26 | 27 | @include make-animation(nutZoom); 28 | 29 | 30 | @keyframes nutFadeZoomIn { 31 | 0% { 32 | opacity: 0; 33 | transform: scale3d(0.3, 0.3, 0.3); 34 | } 35 | 36 | 50% { 37 | opacity: 1; 38 | } 39 | } 40 | 41 | @keyframes nutFadeZoomOut { 42 | 0% { 43 | opacity: 1; 44 | } 45 | 46 | 50% { 47 | opacity: 0; 48 | transform: scale3d(0.3, 0.3, 0.3); 49 | } 50 | 51 | 100% { 52 | opacity: 0; 53 | } 54 | } 55 | 56 | @include make-animation(nutFadeZoom); 57 | -------------------------------------------------------------------------------- /packages/nutui/components/swipegroup/swipegroup.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 40 | -------------------------------------------------------------------------------- /packages/nutui/components/tag/tag.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export type TagType = 'primary' | 'success' | 'danger' | 'warning' 4 | 5 | export const tagProps = { 6 | customColor: { type: String, default: '' }, 7 | textColor: { type: String, default: '' }, 8 | type: { 9 | type: String as PropType, 10 | default: 'default', 11 | }, 12 | plain: { 13 | type: Boolean, 14 | default: false, 15 | }, 16 | round: { 17 | type: Boolean, 18 | default: false, 19 | }, 20 | mark: { 21 | type: Boolean, 22 | default: false, 23 | }, 24 | closeable: { 25 | type: Boolean, 26 | default: false, 27 | }, 28 | } 29 | 30 | export type TagProps = ExtractPropTypes 31 | 32 | export const tagEmits = { 33 | click: (evt: any) => true, 34 | close: (evt: any) => true, 35 | 36 | } 37 | 38 | export type TagEmits = typeof tagEmits 39 | -------------------------------------------------------------------------------- /docs/guide/i18n.md: -------------------------------------------------------------------------------- 1 | # 国际化 2 | 3 | ## 介绍 4 | 5 | `nutui-uniapp` 同步了Taro版的国际化支持,组件默认使用中文。具体可参照以下方式进行国际化设置 6 | 7 | ## 使用方法 8 | 9 | ### 多语言切换 10 | 11 | nutui-uniapp 通过 `Locale` 组件实现多语言支持,使用 `Locale.use` 方法可以切换当前使用的语言。 12 | 13 | ```js 14 | import { EnUSLang, Locale } from 'nutui-uniapp/locale' 15 | 16 | Locale.use('en-US', EnUSLang()) 17 | ``` 18 | 19 | ### 覆盖语言包 20 | 21 | 通过 `Locale.merge` 方法可以实现文案的修改和扩展,示例如下: 22 | 23 | ```js 24 | import { Locale } from 'nutui-uniapp/locale' 25 | 26 | Locale.merge({ 27 | confirm: '确实', 28 | }) 29 | ``` 30 | 31 | ### 目前支持的语言 32 | 33 | | 语言 | 文件名 | 版本 | 34 | | -------- | ------ | -------- | 35 | | 英语 | EnUSLang | `v0.0.1` | 36 | | 简体中文 | ZhCNLang | `v0.0.1` | 37 | | 繁體中文 | ZhTWLang | `v0.0.1` | 38 | | 印度尼西亚语 | IdIDLang | `v0.0.1` | 39 | 40 | ## 常见问题 41 | 42 | ### 找不到所需的语言包? 43 | 44 | 如果上方列表中没有你需要的语言,欢迎给我们提 `Pull Request` 来增加新的语言包。 45 | 46 | ### 业务代码如何实现国际化? 47 | 48 | 可以使用 `vue-i18n` 来实现。 49 | -------------------------------------------------------------------------------- /packages/nutui/components/circleprogress/circleprogress.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export type CircleProgressStrokeLinecap = 'butt' | 'round' | 'square' 4 | 5 | export const circleprogressProps = { 6 | progress: { 7 | type: [Number, String], 8 | default: 0, 9 | }, 10 | strokeWidth: { 11 | type: [Number, String], 12 | default: 5, 13 | }, 14 | radius: { 15 | type: [Number, String], 16 | default: 50, 17 | }, 18 | strokeLinecap: { 19 | type: String as PropType, 20 | default: 'round', 21 | }, 22 | customColor: { 23 | type: [String, Object], 24 | default: '#FF673E', 25 | }, 26 | pathColor: { 27 | type: String, 28 | default: '#d9d9d9', 29 | }, 30 | clockwise: { 31 | type: Boolean, 32 | default: true, 33 | }, 34 | } 35 | 36 | export type CircleProgressProps = ExtractPropTypes 37 | -------------------------------------------------------------------------------- /packages/nutui/components/_hooks/useInject.ts: -------------------------------------------------------------------------------- 1 | import { computed, getCurrentInstance, inject, onUnmounted, ref } from 'vue' 2 | import type { ComponentInternalInstance, InjectionKey } from 'vue' 3 | 4 | type ParentProvide = T & { 5 | add(child: ComponentInternalInstance): void 6 | remove(child: ComponentInternalInstance): void 7 | internalChildren: ComponentInternalInstance[] 8 | } 9 | 10 | export function useInject(key: InjectionKey>) { 11 | const parent = inject(key, null) 12 | 13 | if (parent) { 14 | const instance = getCurrentInstance()! 15 | const { add, remove, internalChildren } = parent 16 | 17 | add(instance) 18 | onUnmounted(() => remove(instance)) 19 | 20 | const index = computed(() => internalChildren.indexOf(instance)) 21 | 22 | return { 23 | parent, 24 | index, 25 | } 26 | } 27 | 28 | return { 29 | parent: null, 30 | index: ref(-1), 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/nutui/components/categorypane/categorypane.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export interface ChildType { 4 | catName?: string 5 | catType?: number 6 | [key: string]: any 7 | } 8 | export interface CustomType { 9 | catName?: string 10 | [key: string]: any 11 | } 12 | export const categorypaneProps = { 13 | // 分类模式 14 | type: { 15 | type: String, 16 | default: 'classify', 17 | }, 18 | 19 | // 右侧导航数据 20 | categoryChild: { 21 | type: Array as PropType, 22 | default: () => [], 23 | }, 24 | 25 | // 模式传入自定义数据 26 | customCategory: { 27 | type: Array as PropType, 28 | default: () => [], 29 | }, 30 | } 31 | 32 | export type CategoryPaneProps = ExtractPropTypes 33 | 34 | export const categorypaneEmits = { 35 | onChange: (sku: string) => true, 36 | } 37 | 38 | export type CategoryPaneEmits = typeof categorypaneEmits 39 | -------------------------------------------------------------------------------- /packages/nutui/components/loadingpage/loadingpage.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const loadingpageProps = { 4 | loadingText: { 5 | type: [String, Number], 6 | default: '正在加载', 7 | }, 8 | image: { 9 | type: String, 10 | default: '', 11 | }, 12 | loading: { 13 | type: Boolean, 14 | default: false, 15 | }, 16 | // 背景色 17 | bgColor: { 18 | type: String, 19 | default: '#ffffff', 20 | }, 21 | customColor: { 22 | type: String, 23 | default: '#C8C8C8', 24 | }, 25 | fontSize: { 26 | type: [String, Number], 27 | default: 19, 28 | }, 29 | iconSize: { 30 | type: [String, Number], 31 | default: 28, 32 | }, 33 | loadingColor: { 34 | type: String, 35 | default: '#C8C8C8', 36 | }, 37 | zIndex: { 38 | type: Number, 39 | default: 9999, 40 | }, 41 | } 42 | 43 | export type LoadingPageProps = ExtractPropTypes 44 | -------------------------------------------------------------------------------- /docs/.vitepress/scripts/pwa.ts: -------------------------------------------------------------------------------- 1 | import type { VitePWAOptions } from 'vite-plugin-pwa' 2 | 3 | export const pwa: Partial = { 4 | base: '/', 5 | scope: '/', 6 | manifest: { 7 | name: 'nutui-uniapp', 8 | short_name: 'nutui-uniapp', 9 | theme_color: '#ffffff', 10 | icons: [ 11 | { 12 | src: 'pwa-192x192.png', 13 | sizes: '192x192', 14 | type: 'image/png', 15 | }, 16 | { 17 | src: 'pwa-512x512.png', 18 | sizes: '512x512', 19 | type: 'image/png', 20 | }, 21 | { 22 | src: 'pwa-512x512.png', 23 | sizes: '512x512', 24 | type: 'image/png', 25 | purpose: 'any maskable', 26 | }, 27 | ], 28 | }, 29 | workbox: { 30 | globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'], 31 | }, 32 | devOptions: { 33 | enabled: true, 34 | suppressWarnings: true, 35 | navigateFallback: '/', 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /packages/nutui/components/list/type.ts: -------------------------------------------------------------------------------- 1 | export interface CachedPosition { 2 | index: number 3 | top: number 4 | bottom: number 5 | height: number 6 | dValue: number 7 | } 8 | 9 | export enum CompareResult { 10 | eq = 1, 11 | lt, 12 | gt, 13 | } 14 | 15 | export function binarySearch(list: T[], value: VT, compareFunc: (current: T, value: VT) => CompareResult) { 16 | let start = 0 17 | let end = list.length - 1 18 | let tempIndex: number | null = null 19 | 20 | while (start <= end) { 21 | tempIndex = Math.floor((start + end) / 2) 22 | const midValue = list[tempIndex] 23 | 24 | const compareRes: CompareResult = compareFunc(midValue, value) 25 | if (compareRes === CompareResult.eq) 26 | return tempIndex 27 | 28 | if (compareRes === CompareResult.lt) 29 | start = tempIndex + 1 30 | 31 | else if (compareRes === CompareResult.gt) 32 | end = tempIndex - 1 33 | } 34 | 35 | return tempIndex! 36 | } 37 | -------------------------------------------------------------------------------- /packages/nutui/components/swipe/swipe.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const swipeProps = { 4 | name: { 5 | type: String, 6 | default: '', 7 | }, 8 | touchMoveStopPropagation: { 9 | type: Boolean, 10 | default: false, 11 | }, 12 | touchMovePreventDefault: { 13 | type: Boolean, 14 | default: false, 15 | }, 16 | disabled: { 17 | type: Boolean, 18 | default: false, 19 | }, 20 | } 21 | 22 | export type SwipeProps = ExtractPropTypes 23 | 24 | export type SwipePosition = 'left' | 'right' | '' 25 | 26 | export const swipeEmits = { 27 | open: (info: { name: string; position: SwipePosition }) => info, 28 | close: (info: { name: string; position: SwipePosition }) => info, 29 | click: (val: any) => true, 30 | } 31 | 32 | export type SwipeEmits = typeof swipeEmits 33 | 34 | export interface SwipeInts { 35 | open: (position?: SwipePosition) => void 36 | close: () => void 37 | } 38 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # https://vitepress.dev/reference/default-theme-home-page 3 | layout: home 4 | 5 | hero: 6 | name: NutUi-uniapp 7 | text: 京东风格的轻量级移动端组件库 8 | tagline: 一个基于 Vue.js与 uni-app 的UI 库,允许你制作漂亮的小程序 9 | image: 10 | src: 'https://s2.loli.net/2023/08/30/foMY3ui4nQpUA1C.png' 11 | alt: NutUi 12 | 13 | actions: 14 | - theme: brand 15 | text: 快速开始 16 | link: /guide/overview 17 | 18 | features: 19 | - icon: 🌈 20 | title: 组件设计 21 | details: 基于NutUi 4.x,适配了uni-app,使用 Vue 技术栈开发小程序应用,开箱即用,帮助研发快速开发用户界面,提升开发效率,改善开发体验。 22 | # link: /guide/overview.html 23 | # linkText: 快速开始 24 | - icon: 🔥 25 | title: 按需引入 26 | details: 提供解析器以自动仅导入被使用的组件。 27 | link: /guide/quick-start.html 28 | linkText: 了解更多 29 | - icon: 🎉 30 | title: TS 支持 31 | details: 支持 TypeScript & 类型检查 & 类型推断。 32 | - icon: ⚙️ 33 | title: 主题配置 34 | details: NutUI 支持灵活的样式定制,满足多种视觉业务和品牌需求,包括但不限于全局主色调和特定组件视觉定制的支持。 35 | 36 | --- 37 | 38 | -------------------------------------------------------------------------------- /packages/nutui/components/invoice/index.scss: -------------------------------------------------------------------------------- 1 | @import '../button/index'; 2 | @import '../radiogroup/index'; 3 | @import '../radio/index'; 4 | @import '../form/index'; 5 | @import '../formitem/index'; 6 | 7 | .nut-theme-dark { 8 | .nut-invoice { 9 | .nut-invoice__submit { 10 | background: $dark-background2; 11 | } 12 | } 13 | } 14 | 15 | .nut-invoice { 16 | position: relative; 17 | width: 100%; 18 | 19 | .nut-cell { 20 | align-items: baseline; 21 | } 22 | 23 | &__submit { 24 | position: fixed; 25 | bottom: 0; 26 | bottom: constant(safe-area-inset-bottom); 27 | bottom: env(safe-area-inset-bottom); 28 | box-sizing: border-box; 29 | display: flex; 30 | align-items: center; 31 | justify-content: center; 32 | width: 100%; 33 | padding: $invoice-padding; 34 | background: #fff; 35 | } 36 | 37 | .nut-radio { 38 | display: inline-block; 39 | margin-right: 6px; 40 | margin-bottom: 0; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/nutui/components/timeselect/timeselect.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const timeselectProps = { 4 | visible: { 5 | type: Boolean, 6 | defalut: false, 7 | }, 8 | height: { 9 | type: [String], 10 | default: '20%', 11 | }, 12 | title: { 13 | type: String, 14 | default: '', 15 | }, 16 | currentKey: { 17 | type: [Number, String], 18 | default: 0, 19 | }, 20 | currentTime: { 21 | type: Array, 22 | default: () => { 23 | return [] 24 | }, 25 | }, 26 | muti: { 27 | type: [Boolean], 28 | default: false, 29 | }, 30 | lockScroll: { 31 | type: [Boolean], 32 | default: true, 33 | }, 34 | } 35 | 36 | export type TimeSelectProps = ExtractPropTypes 37 | 38 | export const timeselectEmits = { 39 | 'update:visible': (val: boolean) => true, 40 | 'select': (val: any) => true, 41 | 42 | } 43 | 44 | export type TimeSelectEmits = typeof timeselectEmits 45 | -------------------------------------------------------------------------------- /packages/nutui/components/menu/menu.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const menuProps = { 4 | activeColor: { 5 | type: String, 6 | default: '', 7 | }, 8 | overlay: { 9 | type: Boolean, 10 | default: true as const, 11 | }, 12 | lockScroll: { 13 | type: Boolean, 14 | default: true as const, 15 | }, 16 | duration: { 17 | type: [Number, String], 18 | default: 300, 19 | }, 20 | titleIcon: String, 21 | 22 | closeOnClickOverlay: { 23 | type: Boolean, 24 | default: true, 25 | }, 26 | direction: { 27 | type: String, 28 | default: 'down', 29 | }, 30 | scrollFixed: { 31 | type: [Boolean, String, Number], 32 | default: false, 33 | }, 34 | titleClass: [String], 35 | upIcon: { 36 | type: String, 37 | default: 'rect-up', 38 | }, 39 | downIcon: { 40 | type: String, 41 | default: 'rect-down', 42 | }, 43 | } 44 | 45 | export type MenuProps = ExtractPropTypes 46 | -------------------------------------------------------------------------------- /packages/nutui/components/list/list.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const clientHeight = uni.getSystemInfoSync().windowHeight || 667 4 | 5 | export const listProps = { 6 | height: { 7 | type: [Number], 8 | default: 50, 9 | }, 10 | listData: { 11 | type: Array, 12 | default: () => { 13 | return [] 14 | }, 15 | }, 16 | bufferSize: { 17 | type: Number, 18 | default: 5, 19 | }, 20 | containerHeight: { 21 | type: [Number], 22 | default: clientHeight, 23 | }, 24 | estimateRowHeight: { 25 | type: Number, 26 | default: 80, 27 | }, 28 | margin: { 29 | type: Number, 30 | default: 10, 31 | }, 32 | } 33 | 34 | export type ListProps = ExtractPropTypes 35 | 36 | export const listEmits = { 37 | // scrollUp: (val: number) => true, 38 | // scrollDown: (val: number) => true, 39 | scrollBottom: () => true, 40 | scroll: () => true, 41 | } 42 | 43 | export type ListEmits = typeof listEmits 44 | -------------------------------------------------------------------------------- /packages/nutui/components/avatargroup/avatargroup.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import type { AvatarShape, AvatarSize } from '../avatar' 3 | 4 | export const AVATAR_KEY = Symbol('avatarGroup') 5 | export const avatargroupProps = { 6 | maxContent: { 7 | type: String, 8 | default: '', 9 | }, 10 | maxCount: { 11 | type: [Number, String], 12 | default: '', 13 | }, 14 | maxBgColor: { 15 | type: String, 16 | default: '#eee', 17 | }, 18 | maxColor: { 19 | type: String, 20 | default: '#666', 21 | }, 22 | size: { 23 | type: String as PropType || Number, 24 | default: 'normal', 25 | }, 26 | shape: { 27 | type: String as PropType, 28 | default: 'round', 29 | }, 30 | span: { 31 | type: String, 32 | default: '-8', 33 | }, 34 | zIndex: { 35 | type: String, 36 | default: 'left', 37 | }, 38 | } 39 | 40 | export type AvatarGroupProps = ExtractPropTypes 41 | -------------------------------------------------------------------------------- /packages/nutui/components/imagepreview/types.ts: -------------------------------------------------------------------------------- 1 | import type { Interceptor } from '../_utils' 2 | 3 | export interface ImageInterface { 4 | src: string 5 | } 6 | 7 | export interface ImagePreviewOptions { 8 | show: boolean 9 | images: ImageInterface[] 10 | videos: [] 11 | contentClose: boolean 12 | initNo: number 13 | paginationVisible: boolean 14 | paginationColor: string 15 | autoplay: [number, string] 16 | isWrapTeleport: boolean 17 | showIndex?: boolean 18 | closeable?: boolean 19 | closeIcon?: string 20 | closeIconPosition?: string 21 | beforeClose?: Interceptor 22 | maxZoom?: number 23 | minZoom?: number 24 | isLoop?: boolean 25 | close?(): void 26 | change?(index: number): void 27 | } 28 | 29 | export const baseProps = { 30 | show: { type: Boolean, default: false }, 31 | initNo: { type: Number, default: 0 }, 32 | showIndex: { type: Boolean, default: true }, 33 | minZoom: { type: Number, default: 1 / 3 }, 34 | maxZoom: { type: Number, default: 3 }, 35 | } 36 | -------------------------------------------------------------------------------- /example/pages.config.ts: -------------------------------------------------------------------------------- 1 | // pages.config.ts 2 | import { defineUniPages } from '@uni-helper/vite-plugin-uni-pages' 3 | import { isH5 } from '@uni-helper/uni-env' 4 | 5 | export default defineUniPages({ 6 | // You can also define pages fields, which have the highest priority. 7 | // easycom: { 8 | // autoscan: true, 9 | // custom: { 10 | // '^nut-(.*)?-(.*)': 'uniapp-nutui/components/$1$2/$1$2.vue', 11 | // '^nut-(.*)': 'uniapp-nutui/components/$1/$1.vue', 12 | 13 | // }, 14 | // }, 15 | pages: [ 16 | { 17 | path: 'pages/index/index', 18 | type: 'home', 19 | }, 20 | ], 21 | globalStyle: { 22 | navigationBarBackgroundColor: '@navBgColor', 23 | navigationBarTextStyle: '@navTxtStyle', 24 | navigationBarTitleText: 'NutUi', 25 | backgroundColor: '@bgColor', 26 | backgroundTextStyle: '@bgTxtStyle', 27 | backgroundColorTop: '@bgColorTop', 28 | backgroundColorBottom: '@bgColorBottom', 29 | navigationStyle: isH5 ? 'custom' : 'default', 30 | }, 31 | }) 32 | -------------------------------------------------------------------------------- /packages/nutui/components/dollmachine/dollmachine.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const dollmachineProps = { 4 | defaultClaw: { 5 | type: String, 6 | default: 7 | 'https://img14.360buyimg.com/imagetools/jfs/t1/146467/34/22553/4178/61b088afE198f676e/21952e7018d1d141.png', 8 | }, 9 | activeClaw: { 10 | type: String, 11 | default: 12 | 'https://img13.360buyimg.com/imagetools/jfs/t1/218082/28/7092/15914/61b088afEf9c253f7/8392e2b14bd8f43a.png', 13 | }, 14 | speed: { 15 | type: Number, 16 | default: 20, 17 | }, 18 | prizeList: { 19 | type: Array, 20 | default: () => [], 21 | }, 22 | prizeIndex: { 23 | type: Number, 24 | default: -1, 25 | }, 26 | } 27 | 28 | export type DollMachineProps = ExtractPropTypes 29 | 30 | export const dollmachineEmits = { 31 | click: () => true, 32 | startTurns: () => true, 33 | endTurns: () => true, 34 | } 35 | 36 | export type DollMachineEmits = typeof dollmachineEmits 37 | -------------------------------------------------------------------------------- /example/src/manifest.json: -------------------------------------------------------------------------------- 1 | {"name":"NutUi","appid":"__UNI__D989E4B","description":"","versionName":"1.0.0","versionCode":"100","transformPx":false,"app-plus":{"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"splashscreen":{"alwaysShowBeforeRender":true,"waiting":true,"autoclose":true,"delay":0},"modules":{},"distribute":{"android":{"permissions":[]},"ios":{"dSYMs":false},"sdkConfigs":{"ad":{}}},"darkmode":true},"quickapp":{},"mp-weixin":{"appid":"wxd4e6c25454525507","setting":{"urlCheck":false,"es6":true,"minified":true,"postcss":true},"usingComponents":true,"lazyCodeLoading":"requiredComponents","darkmode":true,"themeLocation":"theme.json"},"mp-alipay":{"usingComponents":true,"appid":"wxd4e6c25454525507","setting":{"urlCheck":false,"es6":true,"minified":true,"postcss":true},"lazyCodeLoading":"requiredComponents","darkmode":true,"themeLocation":"theme.json"},"mp-baidu":{"usingComponents":true},"mp-toutiao":{"usingComponents":true},"uniStatistics":{"enable":false},"vueVersion":"3","h5":{"darkmode":true,"themeLocation":"theme.json"}} -------------------------------------------------------------------------------- /packages/nutui/components/overlay/overlay.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties, ExtractPropTypes, PropType } from 'vue' 2 | import { isBoolean } from '../_utils' 3 | 4 | export const overlayProps = { 5 | visible: { 6 | type: Boolean, 7 | default: false, 8 | }, 9 | zIndex: { 10 | type: [Number, String], 11 | default: 300, 12 | }, 13 | duration: { 14 | type: [Number, String], 15 | default: 300, 16 | }, 17 | overlayClass: { 18 | type: String, 19 | default: '', 20 | }, 21 | lockScroll: { 22 | type: Boolean, 23 | default: false, 24 | }, 25 | overlayStyle: { 26 | type: Object as PropType, 27 | }, 28 | closeOnClickOverlay: { 29 | type: Boolean, 30 | default: true, 31 | }, 32 | } 33 | 34 | export type OverlayProps = ExtractPropTypes 35 | 36 | export const overlayEmits = { 37 | 'update:visible': (visible: boolean) => isBoolean(visible), 38 | 'click': (evt: any) => evt instanceof Object, 39 | } 40 | 41 | export type OverlayEmits = typeof overlayEmits 42 | -------------------------------------------------------------------------------- /packages/nutui/components/price/price.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { commonProps } from '../_utils' 3 | 4 | export type PriceSize = 'small' | 'normal' | 'large' 5 | export type PricePosition = 'before' | 'after' 6 | 7 | export const priceProps = { 8 | ...commonProps, 9 | price: { 10 | type: [Number, String], 11 | default: 0, 12 | }, 13 | needSymbol: { 14 | type: Boolean, 15 | default: true, 16 | }, 17 | symbol: { 18 | type: String, 19 | default: '¥', 20 | }, 21 | decimalDigits: { 22 | type: Number, 23 | default: 2, 24 | }, 25 | thousands: { 26 | type: Boolean, 27 | default: false, 28 | }, 29 | position: { 30 | type: String as PropType, 31 | default: 'before', 32 | }, 33 | size: { 34 | type: String as PropType, 35 | default: 'normal', 36 | }, 37 | strikeThrough: { 38 | type: Boolean, 39 | default: false, 40 | }, 41 | } 42 | 43 | export type PriceProps = ExtractPropTypes 44 | -------------------------------------------------------------------------------- /packages/nutui/components/formitem/formitem.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export const formitemProps = { 4 | prop: { 5 | type: String, 6 | default: '', 7 | }, 8 | label: { 9 | type: String, 10 | default: '', 11 | }, 12 | rules: { 13 | type: Array as PropType, 14 | default: () => { 15 | return [] 16 | }, 17 | }, 18 | required: { 19 | type: Boolean, 20 | default: false, 21 | }, 22 | showErrorMessage: { 23 | type: Boolean, 24 | default: true, 25 | }, 26 | showErrorLine: { 27 | type: Boolean, 28 | default: true, 29 | }, 30 | labelWidth: { 31 | type: [String, Number], 32 | default: '', 33 | }, 34 | labelAlign: { 35 | type: String, 36 | default: '', 37 | }, 38 | errorMessageAlign: { 39 | type: String, 40 | default: '', 41 | }, 42 | bodyAlign: { 43 | type: String, 44 | default: '', 45 | }, 46 | } 47 | 48 | export type FormItemProps = ExtractPropTypes 49 | -------------------------------------------------------------------------------- /packages/nutui/components/grid/grid.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const GRID_KEY = Symbol('grid') 4 | 5 | export type GridDirection = 'horizontal' | 'vertical' 6 | 7 | export const gridProps = { 8 | // 列数 9 | columnNum: { 10 | type: [Number, String], 11 | default: 4, 12 | }, 13 | // 是否显示边框 14 | border: { 15 | type: Boolean, 16 | default: true, 17 | }, 18 | // 格子之间间隔距离 19 | gutter: { 20 | type: [Number, String], 21 | default: 0, 22 | }, 23 | // 是否内容居中 24 | center: { 25 | type: Boolean, 26 | default: true, 27 | }, 28 | // 是否固定正方形 29 | square: { 30 | type: Boolean, 31 | default: false, 32 | }, 33 | // 内容与文字翻转 34 | reverse: { 35 | type: Boolean, 36 | default: false, 37 | }, 38 | // 内容排列方向 39 | direction: { 40 | type: String as import('vue').PropType, 41 | }, 42 | // 是否开启点击反馈 43 | clickable: { 44 | type: Boolean, 45 | default: false, 46 | }, 47 | } 48 | 49 | export type GridProps = ExtractPropTypes 50 | -------------------------------------------------------------------------------- /docs/guide/overview.md: -------------------------------------------------------------------------------- 1 | # NutUi-uniapp 2 | 3 | ## 介绍 4 | 5 | nutui-uniapp 组件库,基于Taro版[`NutUi`](https://nutui.jd.com) 4.x版本修改而来,适配了uni-app, 使用 Vue 技术栈开发小程序应用,开箱即用,拥有丰富的业务组件。 6 | 7 | 使用请参考[快速开始](./quick-start.md)。 8 | 9 | ## 特性 10 | 11 | - 🚀 80+ 高质量组件,覆盖移动端主流场景 12 | - 💪 支持一套代码同时开发多端 13 | - 📖 基于京东 APP 10.0 视觉规范 14 | - 🍭 支持按需引用 15 | - 💪 支持 TypeScript 16 | - 💪 支持动态定制主题 17 | - 🍭 支持暗黑模式 18 | - 🌍 支持国际化 19 | 20 | ## 预览 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ## 贡献 30 | 31 | 有兴趣贡献的开发人员应该阅读[行为准则](https://github.com/nutui-uniapp/nutui-uniapp/blob/main/CODE_OF_CONDUCT.md)和[贡献指南](https://github.com/nutui-uniapp/nutui-uniapp/blob/main/CONTRIBUTING.md)。 32 | 33 | 感谢所有已经为 nutui-uniapp 做出贡献的人! 34 | 35 | 36 | -------------------------------------------------------------------------------- /packages/nutui/components/marquee/marquee.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const marqueeProps = { 4 | // 抽奖样式 5 | styleOpt: { 6 | type: Object, 7 | default: () => { 8 | return { 9 | itemStyle: {}, 10 | startStyle: {}, 11 | bgStyle: { 12 | background: 'rgb(255, 231, 149)', 13 | }, 14 | } 15 | }, 16 | }, 17 | // 奖品列表 18 | prizeList: { 19 | type: Array, 20 | required: true, 21 | }, 22 | // 中奖奖品的index 23 | prizeIndex: { 24 | type: Number || String, 25 | default: -1, 26 | }, 27 | // 初始转动速度 28 | speed: { 29 | type: Number || String, 30 | default: 150, 31 | }, 32 | // 预抽奖,转动多少次进入抽奖环节 33 | circle: { 34 | type: Number || String, 35 | default: 30, 36 | }, 37 | } 38 | 39 | export type MarqueeProps = ExtractPropTypes 40 | 41 | export const marqueeEmits = { 42 | click: () => true, 43 | startTurns: () => true, 44 | endTurns: () => true, 45 | 46 | } 47 | 48 | export type MarqueeEmits = typeof marqueeEmits 49 | -------------------------------------------------------------------------------- /packages/nutui/components/checkbox/checkbox.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { isBoolean } from '../_utils' 3 | 4 | export const checkboxProps = { 5 | modelValue: { 6 | type: Boolean, 7 | default: false, 8 | }, 9 | disabled: { 10 | type: Boolean, 11 | default: false, 12 | }, 13 | textPosition: { 14 | type: String, 15 | default: 'right', 16 | }, 17 | iconSize: { 18 | type: [String, Number], 19 | default: '', 20 | }, 21 | label: { 22 | type: String, 23 | default: '', 24 | }, 25 | indeterminate: { 26 | type: Boolean, 27 | default: false, 28 | }, 29 | shape: { 30 | type: String as PropType<'round' | 'button'>, 31 | default: 'round', // button 32 | }, 33 | } 34 | 35 | export type CheckboxProps = ExtractPropTypes 36 | 37 | export const checkboxEmits = { 38 | 'change': (val: boolean | string, val2?: string) => true, 39 | 'update:modelValue': (val: boolean | string) => isBoolean(val), 40 | } 41 | 42 | export type CheckboxEmits = typeof checkboxEmits 43 | -------------------------------------------------------------------------------- /packages/nutui/components/hiteggs/hiteggs.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const hiteggsProps = { 4 | num: { 5 | type: Number, 6 | default: 9, 7 | }, 8 | intactImg: { 9 | type: String, 10 | default: 11 | '//img10.360buyimg.com/imagetools/jfs/t1/217651/2/1901/114207/617770f2E74551438/5342f7b949e7bec3.png', 12 | }, 13 | hammer: { 14 | type: String, 15 | default: 16 | '//img13.360buyimg.com/imagetools/jfs/t1/95159/30/17834/9845/61444874E0f463263/924741cae55efb85.png', 17 | }, 18 | splitImg: { 19 | type: String, 20 | default: 21 | '//img13.360buyimg.com/imagetools/jfs/t1/219949/29/1870/75442/61776f7aE5d1a8e07/a8de5321e4e8071e.png', 22 | }, 23 | width: { 24 | type: String, 25 | default: '80px', 26 | }, 27 | height: { 28 | type: String, 29 | default: '80px', 30 | }, 31 | } 32 | 33 | export type HitEggsProps = ExtractPropTypes 34 | 35 | export const hiteggsEmits = { 36 | click: () => true, 37 | } 38 | 39 | export type HitEggsEmits = typeof hiteggsEmits 40 | -------------------------------------------------------------------------------- /packages/nutui/components/ellipsis/ellipsis.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export type Direction = 'start' | 'end' | 'middle' 4 | 5 | export interface EllipsisedValue { 6 | leading?: string 7 | tailing?: string 8 | } 9 | export const ellipsisProps = { 10 | content: { 11 | type: String, 12 | default: '', 13 | }, 14 | direction: { 15 | type: String as PropType, 16 | default: 'end', 17 | }, 18 | rows: { 19 | type: [Number, String], 20 | default: 1, 21 | }, 22 | expandText: { 23 | type: String, 24 | default: '', 25 | }, 26 | collapseText: { 27 | type: String, 28 | default: '', 29 | }, 30 | symbol: { 31 | type: String, 32 | default: '...', 33 | }, 34 | lineHeight: { 35 | type: [Number, String], 36 | default: '20', 37 | }, 38 | } 39 | 40 | export type EllipsisProps = ExtractPropTypes 41 | 42 | export const ellipsisEmits = { 43 | change: (val: 'expand' | 'collapse') => val, 44 | click: () => true, 45 | } 46 | 47 | export type EllipsisEmits = typeof ellipsisEmits 48 | -------------------------------------------------------------------------------- /packages/nutui/components/elevator/elevator.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { isNumber, isString } from '../_utils' 3 | import type { ElevatorData } from './type' 4 | 5 | export const elevatorProps = { 6 | height: { 7 | type: [Number, String], 8 | default: '200px', 9 | }, 10 | acceptKey: { 11 | type: [String], 12 | default: 'title', 13 | }, 14 | indexList: { 15 | type: Array as PropType, 16 | default: () => { 17 | return [] 18 | }, 19 | }, 20 | isSticky: { 21 | type: [Boolean], 22 | default: false, 23 | }, 24 | spaceHeight: { 25 | type: [Number], 26 | default: 23, 27 | }, 28 | titleHeight: { 29 | type: [Number], 30 | default: 35, 31 | }, 32 | } 33 | 34 | export type ElevatorProps = ExtractPropTypes 35 | 36 | export const elevatorEmits = { 37 | clickItem: (key: string, item: any) => { return { key, item } }, 38 | clickIndex: (key: string) => isString(key), 39 | change: (val: number) => isNumber(val), 40 | } 41 | 42 | export type ElevatorEmits = typeof elevatorEmits 43 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "stylelint-config-standard", 5 | "stylelint-config-standard-scss", 6 | "stylelint-config-recommended-vue", 7 | "stylelint-config-html", 8 | "stylelint-config-recess-order" 9 | ], 10 | "plugins": ["stylelint-order"], 11 | "rules": { 12 | "selector-class-pattern": [ 13 | "^([#a-z][$#{}a-z0-9]*)((-{1,2}|_{2})[$#{}a-z0-9]+)*$", 14 | { 15 | "message": "Expected class selector to be kebab-case" 16 | } 17 | ], 18 | "selector-pseudo-class-no-unknown": [ 19 | true, 20 | { 21 | "ignorePseudoClasses": ["::v-deep","deep","v-deep"] 22 | } 23 | ], 24 | "no-descending-specificity" :null, 25 | "no-empty-source" :null, 26 | "keyframes-name-pattern": "^[a-z]+([A-Z][a-z]*)*$" 27 | }, 28 | "ignoreFiles": [ 29 | "node_modules", 30 | "dist", 31 | "public", 32 | "output", 33 | "coverage", 34 | "temp", 35 | "*.js", 36 | "*.cjs", 37 | "*.mjs", 38 | "*.ts", 39 | "*.tsx", 40 | "*.svg", 41 | "*.gif", 42 | "*.md" 43 | ] 44 | 45 | } -------------------------------------------------------------------------------- /packages/nutui/components/progress/progress.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import type { ProgressSize, ProgressStatus } from './types' 3 | 4 | export const progressProps = { 5 | percentage: { 6 | type: [Number, String], 7 | default: 0, 8 | required: true, 9 | }, 10 | size: { 11 | type: String as PropType, 12 | default: 'base', 13 | }, 14 | status: { 15 | type: String as PropType, 16 | default: 'text', 17 | }, 18 | strokeWidth: { 19 | type: [Number, String], 20 | default: '', 21 | }, 22 | textInside: { 23 | type: Boolean, 24 | default: false, 25 | }, 26 | showText: { 27 | type: Boolean, 28 | default: true, 29 | }, 30 | strokeColor: { 31 | type: String, 32 | default: '', 33 | }, 34 | textColor: { 35 | type: String, 36 | default: '', 37 | }, 38 | textBackground: { 39 | type: String, 40 | default: '', 41 | }, 42 | isShowPercentage: { 43 | type: Boolean, 44 | default: true, 45 | }, 46 | } 47 | 48 | export type ProgressProps = ExtractPropTypes 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 yang1206 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 | -------------------------------------------------------------------------------- /docs/guide/theme.md: -------------------------------------------------------------------------------- 1 | # 定制主题 2 | 3 | ### 介绍 4 | 5 | nutui-uniapp 支持灵活的样式定制,满足多种视觉业务和品牌需求,包括但不限于全局主色调和特定组件视觉定制的支持。 6 | 7 | ### 方式一: 使用 CSS Variables 进行主题配置 8 | 9 | `nutui-uniapp` 组件可以通过 CSS Vars 来组织样式,通过覆盖这些 CSS 变量,可以实现定制主题、动态切换主题等功能。 每个组件变量都在各个组件文档底部详细提供。 10 | 11 | 您可在 ConfigProvider 组件 进行体验。 12 | 13 | 我们更推荐使用替换 CSS Vars 的方式来进行个性化的主题配置。 14 | 15 | ### 使用 Sass 变量 进行主题配置 16 | 17 | #### 1. 新建自定义变量 SCSS 文件 18 | 在本地项目中新建一个 SCSS 文件 custom_theme.scss 进行自定义。 19 | 20 | ```scss 21 | // 主色调 22 | $primary-color: #478EF2; 23 | $primary-color-end: #496AF2; 24 | ``` 25 | 26 | #### 2. 修改 vite配置文件 27 | 28 | ```ts 29 | // vite.config.ts 30 | import { defineConfig } from 'vite' 31 | 32 | // https://vitejs.dev/config/ 33 | export default defineConfig({ 34 | // ... 35 | css: { 36 | preprocessorOptions: { 37 | scss: { 38 | additionalData: '@import \'@/assets/custom_theme.scss\';@import \'nutui-uniapp/styles/variables.scss\';', 39 | }, 40 | }, 41 | }, 42 | }) 43 | ``` 44 | 45 | ### 自定义组件的 style 或 class 46 | 47 | 在微信小程序环境组件的 class 和 style 不会被成功编译,如果你想自定义某些组件的 class 或 style,请传递props `customClass`和`customStyle`,目前不是每个组件都支持,后续会考虑支持到每个组件 48 | -------------------------------------------------------------------------------- /packages/nutui/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 yang1206 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 | -------------------------------------------------------------------------------- /docs/components/bingo/giftbox.md: -------------------------------------------------------------------------------- 1 | # GiftBox 神秘大礼盒 2 | 3 | ### 介绍 4 | 5 | 用于礼盒抽奖,可配置图片、开始结束回调等。 6 | 7 | ### 基础用法 8 | 9 | ```html 10 | 11 | 16 | 17 | 再来一次 18 | 19 | 42 | ``` 43 | 44 | ### Events 45 | 46 | | 字段 | 说明 | 回调参数 | 47 | | ----------- | ---------------------- | -------- | 48 | | init | 礼盒初始化 | - | 49 | | start-turns | 礼盒打开时候的回调函数 | - | 50 | | end-turns | 礼盒打开后的回调函数 | - | 51 | -------------------------------------------------------------------------------- /packages/nutui/components/notify/index.scss: -------------------------------------------------------------------------------- 1 | @import '../popup/index'; 2 | 3 | .nut-fade-enter-active { 4 | transition: opacity 1s; 5 | } 6 | 7 | .nut-fade-leave-active { 8 | transition: opacity 1s; 9 | } 10 | 11 | .nut-fade-enter-from, 12 | .nut-fade-leave-to { 13 | opacity: 0; 14 | } 15 | 16 | .nut-notify { 17 | box-sizing: border-box; 18 | display: block; 19 | width: 100%; 20 | height: $notify-height; 21 | padding: $notify-padding; 22 | font-size: $notify-font-size; 23 | line-height: $notify-line-height; 24 | color: $notify-text-color; 25 | text-align: center; 26 | word-wrap: break-word; 27 | white-space: pre-wrap; 28 | 29 | &--base { 30 | background: $notify-base-background-color; 31 | } 32 | 33 | &--primary { 34 | background: $notify-primary-background-color; 35 | } 36 | 37 | &--success { 38 | background: $notify-success-background-color; 39 | } 40 | 41 | &--danger { 42 | background: $notify-danger-background-color; 43 | } 44 | 45 | &--warning { 46 | background: $notify-warning-background-color; 47 | } 48 | 49 | view { 50 | width: 100%; 51 | text-align: center; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/nutui/components/infiniteloading/index.scss: -------------------------------------------------------------------------------- 1 | .nut-infiniteloading { 2 | display: block; 3 | width: 100%; 4 | 5 | .nut-infinite-top { 6 | display: flex; 7 | align-items: center; 8 | justify-content: center; 9 | width: 100%; 10 | overflow: hidden; 11 | 12 | .top-box { 13 | display: flex; 14 | flex-direction: column; 15 | align-items: center; 16 | justify-content: center; 17 | width: 100%; 18 | 19 | .top-img { 20 | width: 28px; 21 | height: 24px; 22 | } 23 | 24 | .top-text { 25 | font-size: 10px; 26 | color: $text-color; 27 | } 28 | } 29 | } 30 | 31 | .nut-infinite-bottom { 32 | display: block; 33 | width: 100%; 34 | padding-top: 16px; 35 | font-size: $font-size-small; 36 | color: $infiniteloading-bottom-color; 37 | text-align: center; 38 | 39 | .bottom-box { 40 | .bottom-img { 41 | width: 28px; 42 | height: 24px; 43 | margin-right: 5px; 44 | } 45 | 46 | .bottom-text { 47 | font-size: 10px; 48 | color: $text-color; 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/nutui/components/row/row.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 45 | -------------------------------------------------------------------------------- /example/src/store/modules/app/index.ts: -------------------------------------------------------------------------------- 1 | import { pinia } from '../../../store' 2 | 3 | interface MenuButtonBoundingClientRect { 4 | width: number 5 | height: number 6 | top: number 7 | left: number 8 | right: number 9 | bottom: number 10 | } 11 | 12 | export const useAppStore = defineStore( 13 | 'app', 14 | () => { 15 | const darkMode = ref(false) 16 | const statusBarHeight = ref(0) 17 | const menuButtonBounding = ref() 18 | const customBarHeight = computed( 19 | () => !menuButtonBounding.value 20 | ? 0 21 | : menuButtonBounding.value.bottom + menuButtonBounding.value.top - statusBarHeight.value, 22 | ) 23 | // #ifdef H5 24 | watch(darkMode, (isDark) => { 25 | isDark ? document.documentElement.classList.add('dark') : document.documentElement.classList.remove('dark') 26 | }, { 27 | immediate: true, 28 | }) 29 | // #endif 30 | return { 31 | darkMode, 32 | statusBarHeight, 33 | customBarHeight, 34 | menuButtonBounding, 35 | } 36 | }, 37 | ) 38 | 39 | export function useAppStoreWidthOut() { 40 | return useAppStore(pinia) 41 | } 42 | -------------------------------------------------------------------------------- /packages/nutui/components/col/col.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request_template.yml: -------------------------------------------------------------------------------- 1 | name: 🚀 新功能请求 Feature Request 2 | description: 对组件库或者仓库本身的建议和想法。 3 | title: '[FR]: ' 4 | labels: [Feature Request] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | **在开始之前...** 10 | 11 | 这个表单仅用于新功能请求。如果你有使用上的问题,或者不确定它是否是一个 bug,请先: 12 | 13 | - 查看组件文档 [nutui-uniapp](https://nutui-uniapp.netlify.app/) 14 | - 在 [Issue](https://github.com/nutui-uniapp/nutui-uniapp/issues) 列表中查找解决方案 15 | - 查看 [常见问题 QA](https://github.com/nutui-uniapp/nutui-uniapp/issues/2461) 16 | - type: textarea 17 | id: problem-description 18 | attributes: 19 | label: 这个功能解决了什么问题? 20 | description: | 21 | 请尽可能详尽地说明这个需求的用例和场景。最重要的是:解释清楚是怎样的用户体验需求催生了这个功能上的需求。 22 | 23 | 通常来说,我们只考虑添加在现有的组件方式无法轻松实现的功能。新功能的用例也应当足够常见。 24 | placeholder: 请填写 25 | validations: 26 | required: true 27 | 28 | - type: textarea 29 | id: proposed-API 30 | attributes: 31 | label: 你期望的组件设计是怎样的? 32 | description: | 33 | 描述一下你期望这个新功能的 API 是如何使用的,并提供一些代码示例。请务必使用 Markdown 格式化你的代码片段。 34 | placeholder: 请填写 35 | validations: 36 | required: true 37 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # 贡献者公约行为准则 2 | 3 | ## 承诺 4 | 5 | 为了促进一个开放和包容的环境,作为贡献者和维护者,我们承诺为每个人提供无骚扰的参与项目和社区的体验,无论年龄、身体大小、残疾、种族、性别特征、性别认同和表达、经验水平、教育、社会经济地位、国籍、个人外貌、种族、宗教或性别认同和取向等。 6 | 7 | ## 行为标准 8 | 9 | 促进积极环境的行为准则: 10 | 11 | - 使用欢迎和包容性的语言 12 | - 尊重不同的观点和经验 13 | - 欢迎建设性批评 14 | - 关注社区最新最好的技术,行为准则等 15 | - 对其他社区成员展示友好 16 | 17 | 不可接受行为示例: 18 | 19 | - 性化语言或图像等 20 | - 挑衅、侮辱、贬低的评论和个人或政治攻击 21 | - 骚扰 22 | - 未经明确允许,发布他人的私人信息 23 | - 其他在职业环境中可以被视为不合适的行为 24 | 25 | ## 责任感 26 | 27 | 项目维护者负责明确可接受行为的标准,并应对任何不可接受行为采取适当和公正的纠正措施。 28 | 29 | 项目维护者有权和责任删除、编辑或拒绝评论、提交、代码、wiki、issue 和其他不符合本行为准则的贡献,暂时或永久禁止任何贡献者参与其他不适当、具有威胁性、冒犯性或有害的行为。 30 | 31 | ## 范围 32 | 33 | 本行为准则适用于所有项目,并且当个人在公共空间代表项目或其社区时也适用。代表项目或社区的示例包括使用官方项目电子邮件地址,通过官方社交媒体账户发布内容,或在在线或离线活动中担任指定代表。项目的代表可以由项目维护者进一步定义和澄清。 34 | 35 | ## 执行 36 | 37 | 如有骚扰或其他不可接受的行为,可以通过联系项目团队 [📪](mailto:y1149221897@outlook.com) 来报告。所有投诉将被审理和调查,在必要和适当的情况下会给予答复。项目团队将会对事件的报告者保密。特定的进一步详细信息可能会单独发布。 38 | 39 | 不遵守或不诚信执行行为准则的项目维护人员可能会面临由项目管理者或其他成员决定的暂时或永久的封禁。 40 | 41 | ## 版权声明 42 | 43 | 本行为准则改编自贡献者公约,版本1.4,可在 [code-of-conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) 获得。 44 | 45 | 有关此行为准则的常见问题的答案,请参见 [Q&A](https://www.contributor-covenant.org/faq)。 46 | -------------------------------------------------------------------------------- /packages/nutui/components/transition/transition.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { commonProps, makeNumberProp } from '../_utils' 3 | import type { NutAnimationName, NutAnimationtimingFunction } from './types' 4 | 5 | export const transitionProps = { 6 | ...commonProps, 7 | name: { 8 | type: String as PropType, 9 | default: 'fade', 10 | }, 11 | show: Boolean, 12 | duration: makeNumberProp(300), 13 | timingFunction: { 14 | type: String as PropType, 15 | default: 'ease', 16 | }, 17 | 18 | enterFromClass: String, 19 | enterActiveClass: String, 20 | enterToClass: String, 21 | leaveFromClass: String, 22 | leaveActiveClass: String, 23 | leaveToClass: String, 24 | 25 | } 26 | 27 | export const transitionEmits = { 28 | beforeEnter: () => true, 29 | enter: () => true, 30 | afterEnter: () => true, 31 | beforeLeave: () => true, 32 | leave: () => true, 33 | afterLeave: () => true, 34 | click: (evt: MouseEvent) => evt, 35 | } 36 | 37 | export type TransitionProps = ExtractPropTypes 38 | export type TransitionEmits = typeof transitionEmits 39 | -------------------------------------------------------------------------------- /packages/nutui/components/sidenavbar/sidenavbar.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 46 | -------------------------------------------------------------------------------- /example/src/pages/demo/bingo/giftbox/index.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 34 | 35 | 36 | 基础用法 37 | 38 | 43 | 44 | 再来一次 45 | 46 | 47 | 48 | 49 | 50 | { 51 | "style": { 52 | "navigationBarTitleText": "GiftBox" 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /packages/nutui/components/avatar/index.scss: -------------------------------------------------------------------------------- 1 | .nut-avatar { 2 | position: relative; 3 | display: inline-block; 4 | flex: 0 0 auto; // 防止被压缩 5 | text-align: center; 6 | vertical-align: top; 7 | background-repeat: no-repeat; 8 | background-position: center center; 9 | background-size: 100% 100%; 10 | 11 | image { 12 | display: block; 13 | width: 100%; 14 | height: 100%; 15 | } 16 | 17 | .nut-icon { 18 | position: absolute; 19 | top: 50%; 20 | left: 50%; 21 | background-size: 100% 100%; 22 | transform: translate(-50%, -50%); 23 | } 24 | } 25 | 26 | .nut-avatar-large { 27 | width: $avatar-large-width; 28 | height: $avatar-large-height; 29 | line-height: $avatar-large-height; 30 | } 31 | 32 | .nut-avatar-small { 33 | width: $avatar-small-width; 34 | height: $avatar-small-height; 35 | line-height: $avatar-small-height; 36 | } 37 | 38 | .nut-avatar-normal { 39 | width: $avatar-normal-width; 40 | height: $avatar-normal-height; 41 | line-height: $avatar-normal-height; 42 | } 43 | 44 | .nut-avatar-round { 45 | border-radius: 50%; 46 | 47 | // overflow: hidden; 48 | } 49 | 50 | .nut-avatar-square { 51 | border-radius: $avatar-square; 52 | } 53 | -------------------------------------------------------------------------------- /packages/nutui/components/fixednav/fixednav.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { isBoolean } from '../_utils' 3 | 4 | export const fixednavProps = { 5 | visible: { 6 | type: Boolean, 7 | default: false, 8 | }, 9 | overlay: { 10 | type: Boolean, 11 | default: true, 12 | }, 13 | navList: { 14 | default: () => [], 15 | type: Array as PropType, 16 | }, 17 | activeColor: { 18 | default: '', 19 | type: String, 20 | }, 21 | activeText: { 22 | default: '', 23 | type: String, 24 | }, 25 | unActiveText: { 26 | default: '', 27 | type: String, 28 | }, 29 | position: { 30 | default: () => { 31 | return { 32 | top: 'auto', 33 | bottom: 'auto', 34 | } 35 | }, 36 | type: Object, 37 | }, 38 | type: { 39 | default: 'right', 40 | type: String, 41 | }, 42 | } 43 | 44 | export type FixednavProps = ExtractPropTypes 45 | 46 | export const fixednavEmits = { 47 | 'update:visible': (val: boolean) => isBoolean(val), 48 | 'selected': (val: { item: any; event: Event }) => { 49 | return val 50 | }, 51 | } 52 | 53 | export type FixednavEmits = typeof fixednavEmits 54 | -------------------------------------------------------------------------------- /packages/nutui/components/notify/notify.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { isBoolean } from '../_utils' 3 | import type { Position } from '../_constants/types' 4 | import type { NotifyType } from './type' 5 | 6 | export const notifyProps = { 7 | customColor: { type: String, default: '' }, 8 | msg: { type: String, default: '' }, 9 | duration: { type: Number, default: 3000 }, 10 | className: { 11 | type: String, 12 | default: '', 13 | }, 14 | background: { type: String, default: '' }, 15 | type: { 16 | type: String as PropType, 17 | default: 'danger', 18 | }, 19 | visible: { 20 | type: Boolean, 21 | default: false, 22 | }, 23 | position: { 24 | type: String as PropType, 25 | default: 'top', 26 | }, 27 | safeAreaInsetTop: { 28 | type: Boolean, 29 | default: false, 30 | }, 31 | safeHeight: { 32 | type: Number, 33 | }, 34 | onClose: Function, 35 | onClick: Function, 36 | } 37 | 38 | export type NotifyProps = ExtractPropTypes 39 | 40 | export const notifyEmits = { 41 | 'update:visible': (val: boolean) => isBoolean(val), 42 | } 43 | 44 | export type NotifyEmits = typeof notifyEmits 45 | -------------------------------------------------------------------------------- /packages/nutui/components/skeleton/skeleton.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import type { AvatarShape } from '../avatar/avatar' 3 | 4 | export const skeletonProps = { 5 | // 每行宽度 6 | width: { 7 | type: String, 8 | default: '100px', 9 | }, 10 | // 每行高度 11 | height: { 12 | type: String, 13 | default: '15px', 14 | }, 15 | // 是否显示动画 16 | animated: { 17 | type: Boolean, 18 | default: false, 19 | }, 20 | // 头像 21 | avatar: { 22 | type: Boolean, 23 | default: false, 24 | }, 25 | // 头像形状:正方形/圆形 26 | avatarShape: { 27 | type: String as import('vue').PropType, 28 | default: 'round', 29 | }, 30 | // 头像大小 31 | avatarSize: { 32 | type: String, 33 | default: '50px', 34 | }, 35 | // 是否显示骨架屏 36 | loading: { 37 | type: Boolean, 38 | default: true, 39 | }, 40 | // 标题/段落 圆角风格 41 | round: { 42 | type: Boolean, 43 | default: false, 44 | }, 45 | 46 | // 显示段落行数 47 | row: { 48 | type: String, 49 | default: '1', 50 | }, 51 | 52 | // 是否显示段落标题 53 | title: { 54 | type: Boolean, 55 | default: true, 56 | }, 57 | } 58 | 59 | export type SkeletonProps = ExtractPropTypes 60 | -------------------------------------------------------------------------------- /packages/nutui/components/pagination/pagination.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { isNumber } from '../_utils' 3 | 4 | export const paginationProps = { 5 | modelValue: { 6 | type: Number, 7 | default: 1, 8 | }, 9 | mode: { 10 | type: String as PropType<'simple' | 'multi'>, 11 | default: 'multi', 12 | }, 13 | prevText: { 14 | type: String, 15 | default: '', 16 | }, 17 | nextText: { 18 | type: String, 19 | default: '', 20 | }, 21 | pageCount: { 22 | type: [String, Number], 23 | default: '', 24 | }, 25 | totalItems: { 26 | type: [String, Number], 27 | default: '0', 28 | }, 29 | itemsPerPage: { 30 | type: [String, Number], 31 | default: '10', 32 | }, 33 | showPageSize: { 34 | type: [String, Number], 35 | default: '5', 36 | }, 37 | forceEllipses: { 38 | type: Boolean, 39 | default: false, 40 | }, 41 | } 42 | 43 | export type PaginationProps = ExtractPropTypes 44 | 45 | export const paginationEmits = { 46 | 'update:modelValue': (val: number) => isNumber(val), 47 | 'change': (val: number) => isNumber(val), 48 | } 49 | 50 | export type PaginationEmits = typeof paginationEmits 51 | -------------------------------------------------------------------------------- /packages/nutui/components/row/index.scss: -------------------------------------------------------------------------------- 1 | .nut-row { 2 | width: 100%; 3 | 4 | &::after { 5 | display: block; 6 | height: 0; 7 | clear: both; 8 | visibility: hidden; 9 | content: ''; 10 | } 11 | 12 | &-flex { 13 | display: flex; 14 | 15 | &::after { 16 | display: none; 17 | } 18 | 19 | .nut-col { 20 | float: none; 21 | } 22 | } 23 | 24 | &-justify-center { 25 | justify-content: center; 26 | } 27 | 28 | &-justify-end { 29 | justify-content: flex-end; 30 | } 31 | 32 | &-justify-space-between { 33 | align-items: center; 34 | justify-content: space-between; 35 | } 36 | 37 | &-justify-space-around { 38 | justify-content: space-around; 39 | } 40 | 41 | &-justify-space-evenly { 42 | justify-content: space-evenly; 43 | } 44 | 45 | &-align-flex-start { 46 | align-items: flex-start; 47 | } 48 | 49 | &-align-center { 50 | align-items: center; 51 | } 52 | 53 | &-align-flex-end { 54 | align-items: flex-end; 55 | } 56 | 57 | &-flex-wrap { 58 | flex-wrap: wrap; 59 | } 60 | 61 | &-flex-nowrap { 62 | flex-wrap: nowrap; 63 | } 64 | 65 | &-flex-reverse { 66 | flex-wrap: wrap-reverse; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /packages/nutui/components/pickercolumn/pickercolumn.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import type { PickerFieldNames, PickerOption } from './types' 3 | 4 | export const pickercolumnProps = { 5 | // 当前选中项 6 | value: [String, Number], 7 | columnsType: String, 8 | column: { 9 | type: Array as PropType, 10 | default: () => [], 11 | }, 12 | // 是否开启3D效果 13 | threeDimensional: { 14 | type: Boolean, 15 | default: true, 16 | }, 17 | swipeDuration: { 18 | type: [Number, String], 19 | default: 1000, 20 | }, 21 | visibleOptionNum: { 22 | type: [Number, String], 23 | default: 7, 24 | }, 25 | optionHeight: { 26 | type: [Number, String], 27 | default: 36, 28 | }, 29 | fieldNames: { 30 | type: Object as PropType>, 31 | default: () => ({}), 32 | }, 33 | // 特殊环境判断 34 | uni: { 35 | type: Boolean, 36 | defualt: false, 37 | }, 38 | } 39 | 40 | export type PickerColumnProps = ExtractPropTypes 41 | 42 | export const pickercolumnEmits = { 43 | click: () => true, 44 | change: (val: PickerOption) => true, 45 | } 46 | 47 | export type PickerColumnEmits = typeof pickercolumnEmits 48 | -------------------------------------------------------------------------------- /packages/nutui/components/tabbar/tabbar.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { isNumber, isString } from '../_utils' 3 | 4 | export const tabbarProps = { 5 | modelValue: { 6 | type: [Number, String], 7 | default: 0, 8 | }, 9 | bottom: { 10 | type: Boolean, 11 | default: false, 12 | }, 13 | type: { 14 | type: String, 15 | default: 'base', 16 | }, 17 | size: { 18 | type: String, 19 | default: '20px', 20 | }, 21 | unactiveColor: { 22 | type: String, 23 | default: '', 24 | }, 25 | activeColor: { 26 | type: String, 27 | default: '', 28 | }, 29 | safeAreaInsetBottom: { 30 | type: Boolean, 31 | default: false, 32 | }, 33 | placeholder: { 34 | type: Boolean, 35 | default: false, 36 | }, 37 | dot: { 38 | type: Boolean, 39 | default: false, 40 | }, 41 | } 42 | 43 | export type TabBarProps = ExtractPropTypes 44 | 45 | export const tabbarEmits = { 46 | 'tabSwitch': (val: any, index: number | string) => { 47 | return { 48 | val, 49 | index, 50 | } 51 | }, 52 | 'update:modelValue': (val: string | number) => isString(val) || isNumber(val), 53 | } 54 | 55 | export type TabBarEmits = typeof tabbarEmits 56 | -------------------------------------------------------------------------------- /scripts/uni.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra' 2 | import consloa from 'consola' 3 | 4 | async function copy() { 5 | const sourceDir = 'packages/nutui' 6 | const destDir = 'packages/uni_modules/dist/nutui-uni' 7 | 8 | await Promise.all([ 9 | fs.remove('packages/uni_modules/dist'), 10 | fs.ensureDir(`${destDir}`), 11 | ]) 12 | 13 | const excludedDir = [ 14 | '_locale', 15 | 'src', 16 | 'node_modules', 17 | 'build.config.ts', 18 | 'env.d.ts', 19 | 'tsconfig.json', 20 | ] 21 | 22 | const excludedDir2 = [ 23 | 'components', 24 | 'locale', 25 | 'dist', 26 | 'styles', 27 | 'global.d.ts', 28 | ] 29 | 30 | const excludedDir3 = [ 31 | 'README.md', 32 | 'LICENSE', 33 | ] 34 | 35 | await Promise.all([ 36 | fs.copy(sourceDir, destDir, { 37 | filter: src => ![...excludedDir, ...excludedDir2].some(d => src.includes(d)), 38 | }).then(() => { 39 | return Promise.all([ 40 | fs.copy(sourceDir, `${destDir}/components/nutui-uni`, { 41 | filter: src => ![...excludedDir, ...excludedDir3].some(d => src.includes(d)), 42 | }), 43 | ]) 44 | }), 45 | 46 | ]).then(() => { 47 | consloa.success('copy success !!!') 48 | }) 49 | } 50 | 51 | copy() 52 | -------------------------------------------------------------------------------- /packages/nutui/components/menuitem/menuitem.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | import { isNumber, isString } from '../_utils' 3 | 4 | export interface MenuItemOption { 5 | text: string 6 | value: number | string 7 | } 8 | 9 | export const menuitemProps = { 10 | title: String, 11 | options: { 12 | type: Array as PropType, 13 | default: [], 14 | }, 15 | disabled: { 16 | type: Boolean, 17 | default: false, 18 | }, 19 | modelValue: null as unknown as PropType, 20 | cols: { 21 | type: Number, 22 | default: 1, 23 | }, 24 | activeTitleClass: String, 25 | inactiveTitleClass: String, 26 | optionIcon: { 27 | type: String, 28 | default: 'Check', 29 | }, 30 | } 31 | 32 | export type MenuItemProps = ExtractPropTypes 33 | 34 | export const menuitemEmits = { 35 | 'update:modelValue': (val: string | number) => isString(val) || isNumber(val), 36 | 'change': (val: string | number) => isString(val) || isNumber(val), 37 | } 38 | export type MenuitemEmits = typeof menuitemEmits 39 | 40 | export interface MenuItemInst { 41 | change: (val?: any) => any 42 | toggle: (show?: boolean) => boolean 43 | open: () => void 44 | close: () => void 45 | } 46 | -------------------------------------------------------------------------------- /packages/nutui/components/rate/rate.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { isNumber } from '../_utils' 3 | 4 | export const rateProps = { 5 | count: { 6 | type: [String, Number], 7 | default: 5, 8 | }, 9 | modelValue: { 10 | type: [String, Number], 11 | default: 0, 12 | }, 13 | customIcon: { 14 | type: String, 15 | default: () => { 16 | return 'star-fill-n' 17 | }, 18 | }, 19 | size: { 20 | type: [String, Number], 21 | default: undefined, 22 | }, 23 | activeColor: { 24 | type: String, 25 | default: '', 26 | }, 27 | voidColor: { 28 | type: String, 29 | default: '', 30 | }, 31 | readonly: { 32 | type: Boolean, 33 | default: false, 34 | }, 35 | disabled: { 36 | type: Boolean, 37 | default: false, 38 | }, 39 | allowHalf: { 40 | type: Boolean, 41 | default: false, 42 | }, 43 | spacing: { 44 | type: [String, Number], 45 | default: undefined, 46 | }, 47 | } 48 | 49 | export type RateProps = ExtractPropTypes 50 | 51 | export const rateEmits = { 52 | 'update:modelValue': (val: number) => isNumber(val), 53 | 'change': (val: number) => isNumber(val), 54 | } 55 | 56 | export type RateEmits = typeof rateEmits 57 | -------------------------------------------------------------------------------- /packages/nutui/components/shortpassword/shortpassword.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { isBoolean, isString } from '../_utils' 3 | 4 | export const shortpasswordProps = { 5 | title: { 6 | type: String, 7 | default: '', 8 | }, 9 | desc: { 10 | type: String, 11 | default: '', 12 | }, 13 | tips: { 14 | type: String, 15 | default: '', 16 | }, 17 | visible: { 18 | type: Boolean, 19 | default: false, 20 | }, 21 | modelValue: { 22 | type: String, 23 | default: '', 24 | }, 25 | errorMsg: { 26 | type: String, 27 | default: '', 28 | }, 29 | closeOnClickOverlay: { 30 | type: Boolean, 31 | default: true, 32 | }, 33 | length: { 34 | type: [String, Number], // 4~6 35 | default: 6, 36 | }, 37 | } 38 | 39 | export type ShortPasswordProps = ExtractPropTypes 40 | 41 | export const shortpasswordEmits = { 42 | 'update:modelValue': (val: string | number, event: Event) => true, 43 | 'update:visible': (val: boolean) => isBoolean(val), 44 | 'complete': (val: string) => isString(val), 45 | 'tips': () => true, 46 | 'close': () => true, 47 | 'focus': () => true, 48 | } 49 | 50 | export type ShortPasswordEmits = typeof shortpasswordEmits 51 | -------------------------------------------------------------------------------- /packages/nutui/components/cellgroup/cellgroup.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 29 | 30 | 31 | 32 | 33 | 34 | {{ title }} 35 | 36 | 37 | 38 | {{ desc }} 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 49 | -------------------------------------------------------------------------------- /packages/nutui/components/skuoperate/index.scss: -------------------------------------------------------------------------------- 1 | .nut-sku-operate { 2 | width: 100%; 3 | 4 | &-desc { 5 | display: block; 6 | width: 100%; 7 | padding: 10px 0; 8 | font-size: 12px; 9 | color: #de6a1c; 10 | text-align: center; 11 | background: #fbf9da; 12 | } 13 | 14 | &-btn { 15 | box-sizing: border-box; 16 | display: flex; 17 | align-items: center; 18 | justify-content: space-between; 19 | width: 100%; 20 | height: $sku-operate-btn-height; 21 | padding: 0 18px; 22 | text-align: center; 23 | background: $white; 24 | border-top: $sku-operate-btn-border-top; 25 | 26 | &-item { 27 | width: 100%; 28 | height: $sku-operate-btn-item-height; 29 | margin-right: 18px; 30 | font-size: $sku-operate-btn-item-font-size; 31 | font-weight: $sku-operate-btn-item-font-weight; 32 | line-height: $sku-operate-btn-item-line-height; 33 | color: $white; 34 | background: $sku-opetate-bg-default; 35 | border-radius: 21px; 36 | 37 | &:last-child { 38 | margin-right: 0; 39 | } 40 | } 41 | 42 | &-buy { 43 | background: $sku-opetate-bg-buy; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /packages/nutui/components/switch/switch.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | import { isBoolean } from '../_utils' 3 | 4 | export const switchProps = { 5 | modelValue: { 6 | type: [String, Number, Boolean], 7 | default: false, 8 | }, 9 | disable: { 10 | type: Boolean, 11 | default: false, 12 | }, 13 | activeColor: { 14 | type: String, 15 | default: '', 16 | }, 17 | inactiveColor: { 18 | type: String, 19 | default: '', 20 | }, 21 | activeText: { 22 | type: String, 23 | default: '', 24 | }, 25 | inactiveText: { 26 | type: String, 27 | default: '', 28 | }, 29 | activeValue: { 30 | type: [String, Number, Boolean], 31 | default: true, 32 | }, 33 | inactiveValue: { 34 | type: [String, Number, Boolean], 35 | default: false, 36 | }, 37 | loading: { 38 | type: Boolean, 39 | default: false, 40 | }, 41 | } 42 | 43 | export type SwitchProps = ExtractPropTypes 44 | 45 | export const switchEmits = { 46 | 'update:modelValue': (val: string | number | boolean) => isBoolean(val), 47 | 'change': (val: any, evt?: Event) => { 48 | return { 49 | val, 50 | evt, 51 | } 52 | }, 53 | } 54 | 55 | export type SwitchEmits = typeof switchEmits 56 | -------------------------------------------------------------------------------- /packages/nutui/_locale/locale.ts: -------------------------------------------------------------------------------- 1 | import { reactive, ref } from 'vue' 2 | import { deepAssign } from '../components/_utils' 3 | import { ZhCNLang } from './lang/zh-CN' 4 | import { EnUSLang } from './lang/en-US' 5 | import { ZhTWLang } from './lang/zh-TW' 6 | import { IdIDLang } from './lang/id-ID' 7 | import type { BaseLang } from './lang/baseLang' 8 | 9 | // 组件默认语言设置 10 | export type langKeys = 'zh-CN' | 'en-US' | 'zh-tw' | 'id-id' 11 | export type Lang = Partial> 12 | 13 | export type DeepPartial = { 14 | [K in keyof T]?: T[K] extends Record ? DeepPartial : T[K] 15 | } 16 | 17 | export { ZhCNLang, EnUSLang, IdIDLang, ZhTWLang } 18 | const currentLang = ref('zh-CN') 19 | const langs = reactive({ 20 | 'zh-CN': ZhCNLang(), 21 | 'en-US': EnUSLang(), 22 | }) 23 | export const useCurrentLang = () => currentLang 24 | 25 | export const Locale = { 26 | 27 | languages(): BaseLang { 28 | return langs[currentLang.value] 29 | }, 30 | 31 | use(lang: keyof Lang, Languages?: DeepPartial) { 32 | currentLang.value = lang 33 | if (Languages) 34 | langs[lang] = Languages 35 | }, 36 | 37 | merge(Languages: DeepPartial) { 38 | deepAssign(this.languages() as any, Languages) 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /packages/nutui/components/addresslist/addresslist.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes } from 'vue' 2 | 3 | export const addresslistProps = { 4 | data: { 5 | type: Array, 6 | default: [], 7 | }, 8 | longPress: { 9 | type: Boolean, 10 | default: false, 11 | }, 12 | swipeEdition: { 13 | type: Boolean, 14 | default: false, 15 | }, 16 | showBottomButton: { 17 | type: Boolean, 18 | default: true, 19 | }, 20 | options: { 21 | type: Object, 22 | default: {}, 23 | }, 24 | } 25 | 26 | export type AddressListProps = ExtractPropTypes 27 | 28 | export const addresslistEmits = { 29 | delIcon: (val: Event, item: unknown, index: number | string) => true, 30 | editIcon: (val: Event, item: unknown, index: number | string) => true, 31 | clickItem: (val: Event, item: unknown, index: number | string) => true, 32 | longCopy: (val: Event, item: unknown, index: number | string) => true, 33 | longSet: (val: Event, item: unknown, index: number | string) => true, 34 | longDel: (val: Event, item: unknown, index: number | string) => true, 35 | swipeDel: (val: Event, item: unknown, index: number | string) => true, 36 | add: (val: Event) => true, 37 | 38 | } 39 | 40 | export type AddressListEmits = typeof addresslistEmits 41 | -------------------------------------------------------------------------------- /packages/nutui/components/input/type.ts: -------------------------------------------------------------------------------- 1 | export type InputAlignType = 'left' | 'center' | 'right' // text-align 2 | export type InputFormatTrigger = 'onChange' | 'onBlur' // onChange: 在输入时执行格式化 ; onBlur: 在失焦时执行格式化 3 | export type InputType = 4 | | 'tel' 5 | | 'url' 6 | | 'date' 7 | | 'file' 8 | | 'text' 9 | | 'time' 10 | | 'week' 11 | | 'color' 12 | | 'digit' 13 | | 'email' 14 | | 'image' 15 | | 'month' 16 | | 'radio' 17 | | 'range' 18 | | 'reset' 19 | | 'button' 20 | | 'hidden' 21 | | 'number' 22 | | 'search' 23 | | 'submit' 24 | | 'checkbox' 25 | | 'password' 26 | | 'textarea' 27 | | 'datetime-local' 28 | | 'idcard' 29 | | 'safe-password' 30 | | 'text' | 'number' | 'idcard' | 'digit' | 'tel' | 'safe-password' | 'nickname' 31 | 32 | export type UniInputType = 'text' | 'number' | 'idcard' | 'digit' | 'tel' | 'safe-password' | 'nickname' 33 | export interface InputRule { 34 | pattern?: RegExp 35 | message?: string 36 | required?: boolean 37 | } 38 | 39 | export type ConfirmTextType = 'send' | 'search' | 'next' | 'go' | 'done' 40 | 41 | export interface InputTarget extends HTMLInputElement { 42 | composing?: boolean 43 | } 44 | 45 | export type InputMode = 'search' | 'tel' | 'url' | 'text' | 'email' | 'none' | 'decimal' | 'numeric' 46 | -------------------------------------------------------------------------------- /packages/nutui/components/guessgift/index.scss: -------------------------------------------------------------------------------- 1 | .nut-guess-gift { 2 | position: relative; 3 | display: flex !important; 4 | align-items: center; 5 | justify-content: center; 6 | 7 | .bowl-item { 8 | position: relative; 9 | top: 0; 10 | left: 0; 11 | z-index: 10; 12 | width: 100px; 13 | height: 100px; 14 | background: url("https://img14.360buyimg.com/imagetools/jfs/t1/213395/37/9376/5774/61cc34b8Ec3d2eddd/1ddf6d42663e1285.png"); 15 | background-repeat: no-repeat; 16 | background-size: 100% 100%; 17 | transition: all ease-out 0.5s; 18 | } 19 | 20 | .gold-bean { 21 | position: absolute; 22 | 23 | // left: 50%; 24 | // transform: translateX(-50%); 25 | bottom: 30px; 26 | z-index: 1; 27 | width: 30px; 28 | height: 30px; 29 | background: url("https://img13.360buyimg.com/imagetools/jfs/t1/219815/14/9349/4725/61cc34b8E059ebbd2/55e8002ae82a01ea.png"); 30 | background-repeat: no-repeat; 31 | background-size: 100% 100%; 32 | } 33 | 34 | // stylelint-disable selector-class-pattern 35 | 36 | ._opacity0 { 37 | opacity: 0; 38 | } 39 | 40 | ._opacity1 { 41 | opacity: 1; 42 | } 43 | } 44 | 45 | .disabledClick { 46 | pointer-events: none !important; 47 | cursor: not-allowed !important; 48 | } 49 | -------------------------------------------------------------------------------- /packages/nutui/components/swiper/index.scss: -------------------------------------------------------------------------------- 1 | .nut-swiper { 2 | position: relative; 3 | box-sizing: content-box; 4 | display: flex; 5 | overflow: hidden; 6 | cursor: grab; 7 | user-select: none; 8 | transition-property: transform; 9 | 10 | &-inner { 11 | display: flex; 12 | height: 100%; 13 | } 14 | 15 | &-vertical { 16 | -webkit-box-orient: vertical; 17 | -webkit-box-direction: normal; 18 | flex-direction: column; 19 | } 20 | 21 | &-pagination { 22 | position: absolute; 23 | bottom: 12px; 24 | left: 50%; 25 | display: flex; 26 | transform: translateX(-50%); 27 | 28 | .pagination { 29 | width: $swiper-pagination-item-width; 30 | height: $swiper-pagination-item-height; 31 | margin-right: $swiper-pagination-item-margin-right; 32 | border-radius: $swiper-pagination-item-border-radius; 33 | 34 | &:last-child { 35 | margin-right: 0; 36 | } 37 | } 38 | } 39 | 40 | &-pagination-vertical { 41 | top: 50%; 42 | bottom: auto; 43 | left: 12px; 44 | flex-direction: column; 45 | transform: translateY(-50%); 46 | -webkit-box-orient: vertical; 47 | -webkit-box-direction: normal; 48 | 49 | .pagination { 50 | margin-bottom: 5px; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/nutui/components/indicator/index.scss: -------------------------------------------------------------------------------- 1 | .nut-indicator { 2 | &--block { 3 | display: block; 4 | width: 100%; 5 | } 6 | 7 | &--align__left { 8 | text-align: left; 9 | } 10 | 11 | &--align__right { 12 | text-align: right; 13 | } 14 | 15 | &--align__center { 16 | text-align: center; 17 | } 18 | 19 | &--dot, 20 | &--number { 21 | margin: 0 4px; 22 | 23 | &:first-child { 24 | margin-left: 0; 25 | } 26 | 27 | &:last-child { 28 | margin-right: 0; 29 | } 30 | } 31 | 32 | &--dot { 33 | display: inline-block; 34 | width: $indicator-dot-size; 35 | height: $indicator-dot-size; 36 | vertical-align: middle; 37 | background-color: $indicator-dot-color; 38 | border-radius: 50%; 39 | } 40 | 41 | &--number { 42 | position: relative; 43 | display: inline-block; 44 | width: $indicator-size; 45 | height: $indicator-size; 46 | font-size: $indicator-number-font-size; 47 | line-height: $indicator-size; 48 | color: $indicator-color; 49 | text-align: center; 50 | vertical-align: middle; 51 | background-color: $indicator-bg-color; 52 | border: 1px solid $indicator-color; 53 | border-radius: 50%; 54 | box-shadow: 0 0 1px 1px $indicator-bg-color; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/nutui/components/grid/grid.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 52 | -------------------------------------------------------------------------------- /packages/nutui/components/indicator/indicator.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 31 | 32 | 33 | 34 | 35 | 36 | {{ (fillZero && padZero(item)) || item }} 37 | 38 | 39 | 40 | 41 | 42 | 43 | 46 | -------------------------------------------------------------------------------- /example/src/pages/demo/exhibition/loadingpage/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 基础用法 11 | 12 | 13 | 14 | 15 | 16 | 自定义图片 17 | 18 | 19 | 20 | 21 | 22 | 自定义加载动画模式 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | { 33 | "style": { 34 | "navigationBarTitleText": "LoadingPage" 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /example/src/pages/demo/business/barrage/index.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 24 | 25 | 26 | 基础用法 27 | 28 | 29 | 30 | 31 | 32 | 33 | 随机添加 34 | 35 | 36 | 37 | 38 | 39 | 51 | 52 | 53 | { 54 | "style": { 55 | "navigationBarTitleText": "Barrage" 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /packages/nutui/components/range/range.ts: -------------------------------------------------------------------------------- 1 | import type { ExtractPropTypes, PropType } from 'vue' 2 | 3 | export type SliderValue = number | number[] 4 | 5 | export const rangeProps = { 6 | range: { 7 | type: Boolean, 8 | default: false, 9 | }, 10 | disabled: Boolean, 11 | activeColor: String, 12 | inactiveColor: String, 13 | buttonColor: String, 14 | vertical: { 15 | type: Boolean, 16 | default: false, 17 | }, 18 | marks: { 19 | type: Object, 20 | default: {}, 21 | }, 22 | hiddenRange: { 23 | type: Boolean, 24 | default: false, 25 | }, 26 | hiddenTag: { 27 | type: Boolean, 28 | default: false, 29 | }, 30 | min: { 31 | type: [Number, String], 32 | default: 0, 33 | }, 34 | max: { 35 | type: [Number, String], 36 | default: 100, 37 | }, 38 | step: { 39 | type: [Number, String], 40 | default: 1, 41 | }, 42 | modelValue: { 43 | type: [Number, Array] as PropType, 44 | default: 0, 45 | }, 46 | } 47 | 48 | export type RangeProps = ExtractPropTypes 49 | 50 | export const rangeEmits = { 51 | 'update:modelValue': (val: SliderValue) => true, 52 | 'dragStart': () => true, 53 | 'change': (val: SliderValue) => true, 54 | 'dragEnd': () => true, 55 | } 56 | 57 | export type RangeEmits = typeof rangeEmits 58 | -------------------------------------------------------------------------------- /example/src/styles/app.scss: -------------------------------------------------------------------------------- 1 | @import './reset.css'; 2 | 3 | html .dark { 4 | .uni-page-head { 5 | background-color: #1B1C1E; 6 | color: white; 7 | } 8 | } 9 | 10 | page, 11 | #app { 12 | width: 100%; 13 | height: 100%; 14 | 15 | .nut-theme-dark{ 16 | .demo{ 17 | background: black !important; 18 | } 19 | } 20 | 21 | .demo { 22 | height: auto; 23 | padding: 0 17px 17px; 24 | overflow-x: hidden; 25 | overflow-y: auto; 26 | background: #f7f8fa; 27 | 28 | 29 | &.full { 30 | padding: 0; 31 | 32 | .title { 33 | padding-left: 27px; 34 | } 35 | } 36 | 37 | &.bg-w { 38 | background: #fff; 39 | } 40 | 41 | &::-webkit-scrollbar { 42 | width: 0; 43 | background: transparent; 44 | } 45 | 46 | > .title { 47 | padding: 0 10px; 48 | margin-top: 30px; 49 | margin-bottom: 10px; 50 | font-size: 14px; 51 | font-weight: normal; 52 | color: rgb(144 156 164 / 100%); 53 | } 54 | 55 | > .p { 56 | font-size: 12px; 57 | } 58 | 59 | .card { 60 | padding: 25px 18px; 61 | background: rgb(255 255 255 / 100%); 62 | } 63 | } 64 | 65 | } 66 | 67 | 68 | /* #ifdef H5 */ 69 | *::-webkit-scrollbar { 70 | --at-apply: w0; 71 | } 72 | /* #endif */ 73 | 74 | -------------------------------------------------------------------------------- /packages/nutui/components/timepannel/timepannel.vue: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 41 | 42 | 43 | 44 | {{ name }} 45 | 46 | 47 | 48 | 51 | -------------------------------------------------------------------------------- /packages/nutui/components/radiogroup/radiogroup.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 51 | --------------------------------------------------------------------------------
23 | 24 | 25 | 26 | 27 |