├── .editorconfig ├── .eslintrc.js ├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── .vscode └── settings.json ├── .yarnrc ├── ARCHITECTURE.md ├── LICENSE ├── README.md ├── examples ├── data-fetch │ ├── README.md │ ├── babel.config.js │ ├── config │ │ ├── dev.js │ │ ├── index.js │ │ └── prod.js │ ├── global.d.ts │ ├── package.json │ ├── project.config.json │ ├── project.tt.json │ ├── src │ │ ├── app.config.ts │ │ ├── app.scss │ │ ├── app.ts │ │ ├── index.html │ │ └── pages │ │ │ ├── index │ │ │ ├── index.config.ts │ │ │ ├── index.h5.tsx │ │ │ ├── index.tsx │ │ │ └── view.tsx │ │ │ └── stars │ │ │ ├── index.h5.tsx │ │ │ ├── index.tsx │ │ │ └── view.tsx │ └── tsconfig.json ├── dynamic-routing │ ├── README.md │ ├── babel.config.js │ ├── config │ │ ├── dev.js │ │ ├── index.js │ │ └── prod.js │ ├── global.d.ts │ ├── package.json │ ├── project.config.json │ ├── project.tt.json │ ├── src │ │ ├── app.config.ts │ │ ├── app.scss │ │ ├── app.ts │ │ ├── index.html │ │ └── pages │ │ │ ├── index │ │ │ └── index.tsx │ │ │ └── post │ │ │ ├── [id] │ │ │ ├── [comment].tsx │ │ │ └── index.tsx │ │ │ ├── index.config.ts │ │ │ ├── index.tsx │ │ │ └── view.tsx │ └── tsconfig.json ├── reactions │ ├── README.md │ ├── babel.config.js │ ├── config │ │ ├── dev.js │ │ ├── index.js │ │ └── prod.js │ ├── global.d.ts │ ├── package.json │ ├── project.config.json │ ├── project.tt.json │ ├── src │ │ ├── app.config.ts │ │ ├── app.scss │ │ ├── app.ts │ │ ├── index.html │ │ └── pages │ │ │ └── index │ │ │ ├── index.config.ts │ │ │ ├── index.h5.tsx │ │ │ ├── index.tsx │ │ │ └── view.tsx │ └── tsconfig.json ├── with-less │ ├── README.md │ ├── babel.config.js │ ├── config │ │ ├── dev.js │ │ ├── index.js │ │ └── prod.js │ ├── global.d.ts │ ├── package.json │ ├── project.config.json │ ├── project.tt.json │ ├── src │ │ ├── app.config.ts │ │ ├── app.less │ │ ├── app.ts │ │ ├── index.html │ │ └── pages │ │ │ └── index │ │ │ ├── index.config.ts │ │ │ ├── index.h5.tsx │ │ │ ├── index.module.less │ │ │ ├── index.tsx │ │ │ └── view.tsx │ └── tsconfig.json └── with-postcss │ ├── README.md │ ├── babel.config.js │ ├── config │ ├── dev.js │ ├── index.js │ └── prod.js │ ├── global.d.ts │ ├── package.json │ ├── postcss-plugins │ └── red-color.js │ ├── project.config.json │ ├── project.tt.json │ ├── src │ ├── app.config.ts │ ├── app.less │ ├── app.ts │ ├── index.html │ └── pages │ │ └── index │ │ ├── index.config.ts │ │ ├── index.h5.tsx │ │ ├── index.module.less │ │ ├── index.tsx │ │ └── view.tsx │ └── tsconfig.json ├── jest.config.js ├── lerna.json ├── package.json ├── packages ├── components │ ├── .dumi │ │ └── theme │ │ │ ├── components │ │ │ ├── layout │ │ │ │ ├── index.scss │ │ │ │ └── index.tsx │ │ │ └── subMenu │ │ │ │ ├── index.scss │ │ │ │ └── index.tsx │ │ │ └── layouts │ │ │ ├── index.scss │ │ │ └── index.tsx │ ├── .umirc.ts │ ├── README.md │ ├── index-style-only.js │ ├── index.js │ ├── package.json │ ├── src │ │ ├── _util │ │ │ ├── children │ │ │ │ └── toArray.ts │ │ │ ├── dom │ │ │ │ └── requestIdleCallback.ts │ │ │ ├── hooks │ │ │ │ ├── useIntersection.ts │ │ │ │ ├── useMergedState.ts │ │ │ │ ├── useTaroBaseEvents.ts │ │ │ │ └── useTaroHoverableEvents.ts │ │ │ ├── taroEvent.ts │ │ │ └── typings.ts │ │ ├── block │ │ │ └── index.tsx │ │ ├── button │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── form │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── formContext.ts │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ ├── style │ │ │ │ └── index.ts │ │ │ └── useField.ts │ │ ├── icon │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ └── index.ts │ │ ├── image │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── input │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── label │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ └── index.ts │ │ ├── mask │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── modal │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ └── index.ts │ │ ├── navigator │ │ │ ├── demos │ │ │ │ ├── demo1.tsx │ │ │ │ └── demo2.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── picker-view-column │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ └── index.ts │ │ ├── picker-view │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ ├── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ │ └── wheel.tsx │ │ ├── picker │ │ │ ├── constant.js │ │ │ ├── date.js │ │ │ ├── index.js │ │ │ ├── picker-group.js │ │ │ └── style │ │ │ │ ├── index.js │ │ │ │ └── index.scss │ │ ├── preview │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── progress │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── rich-text │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── scroll-view │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── style │ │ │ ├── index.scss │ │ │ └── index.ts │ │ ├── swiper-item │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ └── index.ts │ │ ├── swiper │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── switch │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── text │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── textarea │ │ │ ├── calculateNodeHeight.ts │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── forceHiddenStyles.ts │ │ │ ├── getSizingData.ts │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── toast │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ ├── index.scss │ │ │ │ └── index.ts │ │ ├── video │ │ │ ├── demos │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ └── index.ts │ │ ├── view │ │ │ ├── demos │ │ │ │ ├── demo1.scss │ │ │ │ └── demo1.tsx │ │ │ ├── index.md │ │ │ ├── index.tsx │ │ │ └── style │ │ │ │ └── index.ts │ │ └── web-view │ │ │ ├── index.tsx │ │ │ └── style │ │ │ ├── index.scss │ │ │ └── index.ts │ ├── taror-tools.config.js │ ├── tsconfig.json │ └── webpack.config.js ├── create-nextjs │ ├── __testfixtures__ │ │ ├── basic.input.js │ │ ├── basic.output.js │ │ ├── no-plugins.input.js │ │ ├── no-plugins.output.js │ │ ├── transformed.input.js │ │ └── transformed.output.js │ ├── __tests__ │ │ └── transform.js │ ├── cli.js │ ├── index.js │ ├── package.json │ └── transform.js └── nextjs │ ├── README.md │ ├── babel │ ├── after.js │ ├── before.js │ ├── class-component-taro-router-plugin.js │ ├── common.js │ ├── next-app-plugin.js │ ├── taro-app-plugin.js │ ├── taro-import-plugin.js │ └── taro-ssg-plugin.js │ ├── build │ ├── getBabelCommonConfig.js │ ├── getTSCommonConfig.js │ └── projectHelper.js │ ├── components │ └── src │ │ └── index.ts │ ├── gulpfile.js │ ├── package.json │ ├── postcss │ ├── index.js │ └── src │ │ ├── index.ts │ │ └── postcss-alias.ts │ ├── router │ ├── index.js │ └── src │ │ └── index.tsx │ ├── src │ ├── constants.ts │ ├── index.ts │ ├── nextUtils │ │ ├── getNextPageInfos.ts │ │ ├── index.ts │ │ ├── isDynamicPage.ts │ │ └── recursiveReadDir.ts │ ├── openBrowser.ts │ ├── scssUtils.ts │ ├── taroUtils │ │ ├── index.ts │ │ └── mergeTaroPages.ts │ └── utils.ts │ ├── taro │ ├── index.js │ └── src │ │ ├── _util │ │ ├── dom.ts │ │ ├── env.ts │ │ ├── handler.ts │ │ ├── index.ts │ │ ├── raf.ts │ │ └── typings.ts │ │ ├── basics │ │ ├── debug.ts │ │ ├── index.ts │ │ ├── performance.ts │ │ ├── system.ts │ │ └── update.ts │ │ ├── canvas │ │ ├── CanvasContext.ts │ │ ├── canvasGetImageData.ts │ │ ├── canvasPutImageData.ts │ │ ├── canvasToTempFilePath.ts │ │ ├── createCanvasContext.ts │ │ └── index.ts │ │ ├── dataCache.ts │ │ ├── device │ │ ├── accelerometer.ts │ │ ├── battery.ts │ │ ├── clipboard.ts │ │ ├── compass.ts │ │ ├── index.ts │ │ ├── motion.ts │ │ ├── network.ts │ │ ├── phone.ts │ │ └── vibrate.ts │ │ ├── dom │ │ ├── index.ts │ │ ├── nodesRef.ts │ │ └── selectorQuery.ts │ │ ├── framework.ts │ │ ├── hooks.ts │ │ ├── index.ts │ │ ├── internal │ │ ├── index.tsx │ │ ├── taroApp.tsx │ │ └── taroPage.tsx │ │ ├── location.ts │ │ ├── media │ │ ├── image.tsx │ │ ├── index.ts │ │ └── video.ts │ │ ├── network │ │ ├── index.ts │ │ ├── request.ts │ │ └── upload.ts │ │ ├── router.ts │ │ ├── swan.d.ts │ │ └── ui │ │ ├── background.ts │ │ ├── index.ts │ │ ├── interactive.tsx │ │ ├── menu.ts │ │ ├── navigationBar.ts │ │ └── roll.ts │ ├── template │ ├── babel.config.ejs │ ├── customRoutes.json │ ├── next.config.ejs │ ├── pages │ │ ├── _app.ejs │ │ └── _document.jsx │ ├── postcss.config.js │ ├── src │ │ └── app.jsx │ └── tsconfig.json │ └── tsconfig.json ├── tests ├── __fixtures__ │ ├── getNextExportedFunctions │ │ ├── function.js │ │ ├── named.js │ │ └── variable.js │ └── template │ │ └── nextConfig │ │ ├── basic.js │ │ └── default.js ├── babel │ ├── class-component-taro-router-plugin │ │ ├── __fixtures__ │ │ │ ├── ignore-function-component │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── method │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── property │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ └── trasformed │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ └── index.spec.js │ ├── next-app-plugin │ │ ├── __fixtures__ │ │ │ └── basic │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ ├── app.js │ │ └── index.spec.js │ ├── next-ssg-plugin │ │ ├── __fixtures__ │ │ │ ├── babel-style-memoized-function │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── class-declarations │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── class-exports │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── destructuring-assignment-array │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── destructuring-assignment-object │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── full-re-export │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── not-mix-up-bindings │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── remove-combined-named-export │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── remove-named-export-async-function │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── remove-named-export-async-variable │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── remove-named-export-function │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── remove-named-export-variable │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── remove-named-export │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── remove-re-exported-function-dependents-variables-functions-imports │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── remove-re-exported-function │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── remove-re-exported-variable │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── retain-extra-named-export-function │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ ├── retain-extra-named-export-variable │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ │ └── retain-extra-named-export │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ └── index.spec.js │ ├── taro-app-plugin │ │ ├── __fixtures__ │ │ │ └── basic │ │ │ │ ├── code.js │ │ │ │ └── output.js │ │ └── index.spec.js │ └── taro-import-plugin │ │ ├── __fixtures__ │ │ ├── basic │ │ │ ├── code.js │ │ │ └── output.js │ │ └── commonjs │ │ │ ├── code.js │ │ │ └── output.js │ │ └── index.spec.js ├── components │ ├── useTaroBaseEvents.spec.tsx │ └── useTaroHoverableEvents.spec.tsx ├── integration │ ├── config │ │ ├── config │ │ │ ├── dev.js │ │ │ ├── index.js │ │ │ └── prod.js │ │ ├── index.spec.ts │ │ └── src │ │ │ ├── app.config.js │ │ │ ├── app.js │ │ │ └── pages │ │ │ └── index │ │ │ └── index.js │ ├── dynamic-routing │ │ ├── config │ │ │ ├── dev.js │ │ │ ├── index.js │ │ │ └── prod.js │ │ ├── index.spec.ts │ │ └── src │ │ │ ├── app.config.js │ │ │ ├── app.js │ │ │ └── pages │ │ │ ├── comment │ │ │ ├── [id] │ │ │ │ ├── [comment].js │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ └── view.js │ │ │ ├── index │ │ │ ├── [id].js │ │ │ ├── index.js │ │ │ └── view.js │ │ │ ├── me │ │ │ ├── index.h5.js │ │ │ ├── index.js │ │ │ └── view.js │ │ │ └── post │ │ │ ├── [id].js │ │ │ ├── index.js │ │ │ └── view.js │ └── watch │ │ ├── config │ │ ├── dev.js │ │ ├── index.js │ │ └── prod.js │ │ ├── index.spec.ts │ │ └── src │ │ ├── app.config.js │ │ └── app.js ├── nextUtils.spec.ts ├── taro │ ├── dataCache.spec.ts │ └── device │ │ └── clipboard.spec.ts ├── taroTestUtils.ts ├── template │ └── nextConfig.spec.ts └── utils.spec.ts ├── tsconfig.json ├── typings └── event-stream.d.ts └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 4 12 | 13 | [*.yaml] 14 | indent_size = 2 15 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | node: true, 6 | jest: true 7 | }, 8 | extends: [ 9 | 'eslint:recommended', 10 | 'plugin:react/recommended', 11 | 'plugin:react-hooks/recommended' 12 | ], 13 | parserOptions: { 14 | ecmaFeatures: { 15 | jsx: true 16 | }, 17 | ecmaVersion: 'latest' 18 | }, 19 | plugins: [ 20 | 'react' 21 | ], 22 | rules: { 23 | 'comma-dangle': 'error', 24 | quotes: ['error', 'single'], 25 | semi: ['error', 'never'], 26 | 'quote-props': ['error', 'as-needed'], 27 | 'no-inner-declarations': 'off', 28 | 'no-empty': 'off', 29 | 'react/react-in-jsx-scope': 'off', 30 | 'no-unused-vars': ['error', { ignoreRestSiblings: true }] 31 | }, 32 | overrides: [ 33 | { 34 | files: ['*.ts', '*.tsx'], 35 | parser: '@typescript-eslint/parser', 36 | extends: [ 37 | 'plugin:@typescript-eslint/recommended' 38 | ], 39 | plugins: [ 40 | '@typescript-eslint' 41 | ], 42 | rules: { 43 | '@typescript-eslint/no-empty-function': 'off', 44 | '@typescript-eslint/no-namespace': 'off', 45 | '@typescript-eslint/ban-types': 'off' 46 | } 47 | } 48 | ], 49 | ignorePatterns: [ 50 | '**/lib/**/*.js', 51 | '**/lib/**/*.ts', 52 | '**/es/**/*.js', 53 | '**/es/**/*.ts', 54 | '**/dist/**/*.js', 55 | '**/dist/**/*.ts', 56 | '**/__fixtures__/**' 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | types: [ opened, synchronize ] 6 | push: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [16.x] 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: Use Node.js ${{ matrix.node-version }} 21 | uses: actions/setup-node@v2 22 | with: 23 | node-version: ${{ matrix.node-version }} 24 | cache: 'yarn' 25 | 26 | - name: Install dependencies 27 | run: yarn 28 | 29 | - name: Build 30 | run: yarn build 31 | 32 | - name: Run Jest tests 33 | run: yarn test 34 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } 4 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | registry "https://registry.npmjs.org/" 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Cong-Cong Pan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | packages/nextjs/README.md -------------------------------------------------------------------------------- /examples/data-fetch/README.md: -------------------------------------------------------------------------------- 1 | # 数据请求示例 2 | 3 | 通过导出 `getStaticProps` Next.js 将在构建阶段获取数据,并将页面预渲染为静态页面。 4 | 5 | ## 执行 Next.js 6 | 7 | ```bash 8 | yarn dev:nextjs 9 | ``` 10 | 11 | ## 执行小程序 12 | 13 | ```bash 14 | yarn dev:swan 15 | ``` 16 | -------------------------------------------------------------------------------- /examples/data-fetch/babel.config.js: -------------------------------------------------------------------------------- 1 | // babel-preset-taro 更多选项和默认值: 2 | // https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md 3 | module.exports = { 4 | presets: [ 5 | ['taro', { 6 | framework: 'react', 7 | ts: true 8 | }] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /examples/data-fetch/config/dev.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"development"' 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/data-fetch/config/prod.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"production"' 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/data-fetch/global.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.png'; 4 | declare module '*.gif'; 5 | declare module '*.jpg'; 6 | declare module '*.jpeg'; 7 | declare module '*.svg'; 8 | declare module '*.css'; 9 | declare module '*.less'; 10 | declare module '*.scss'; 11 | declare module '*.sass'; 12 | declare module '*.styl'; 13 | 14 | declare namespace NodeJS { 15 | interface ProcessEnv { 16 | TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd' 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/data-fetch/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./dist", 3 | "projectname": "data", 4 | "description": "数据请求示例", 5 | "appid": "touristappid", 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": false, 9 | "postcss": false, 10 | "minified": false 11 | }, 12 | "compileType": "miniprogram" 13 | } 14 | -------------------------------------------------------------------------------- /examples/data-fetch/project.tt.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./", 3 | "projectname": "data", 4 | "appid": "testAppId", 5 | "setting": { 6 | "es6": false, 7 | "minified": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/data-fetch/src/app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | pages: [ 3 | 'pages/index/index', 4 | 'pages/stars/index' 5 | ], 6 | window: { 7 | backgroundTextStyle: 'light', 8 | navigationBarBackgroundColor: '#fff', 9 | navigationBarTitleText: 'WeChat', 10 | navigationBarTextStyle: 'black' 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /examples/data-fetch/src/app.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 16px!important; 3 | margin: 8px!important; 4 | font-family: Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji!important; 5 | line-height: 1.5!important; 6 | } 7 | 8 | .paragraph { 9 | margin: 16px 0 16px; 10 | } 11 | 12 | .taro-nav { 13 | text-decoration: underline!important; 14 | } 15 | -------------------------------------------------------------------------------- /examples/data-fetch/src/app.ts: -------------------------------------------------------------------------------- 1 | import { Component } from 'react' 2 | import './app.scss' 3 | 4 | class App extends Component { 5 | 6 | componentDidMount () {} 7 | 8 | componentDidShow () {} 9 | 10 | componentDidHide () {} 11 | 12 | componentDidCatchError () {} 13 | 14 | // this.props.children 是将要会渲染的页面 15 | render () { 16 | return this.props.children 17 | } 18 | } 19 | 20 | export default App 21 | -------------------------------------------------------------------------------- /examples/data-fetch/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/data-fetch/src/pages/index/index.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | navigationBarTitleText: '首页' 3 | } 4 | -------------------------------------------------------------------------------- /examples/data-fetch/src/pages/index/index.h5.tsx: -------------------------------------------------------------------------------- 1 | import {request} from '@tarojs/taro' 2 | export {default} from './view'; 3 | 4 | export async function getStaticProps() { 5 | const res = await request({ 6 | method: 'GET', 7 | url: 'https://api.github.com/repos/NervJS/taro' 8 | }) 9 | 10 | return { 11 | props: { 12 | stars: res.data.stargazers_count 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/data-fetch/src/pages/index/index.tsx: -------------------------------------------------------------------------------- 1 | import {useEffect, useState} from 'react' 2 | import {request} from '@tarojs/taro' 3 | import IndexView from './view'; 4 | 5 | function Index() { 6 | const [stars, setStars] = useState() 7 | 8 | useEffect(() => { 9 | (async function () { 10 | const res = await request({ 11 | method: 'GET', 12 | url: 'https://api.github.com/repos/NervJS/taro' 13 | }) 14 | setStars(res.data.stargazers_count) 15 | })() 16 | }, []) 17 | 18 | return 19 | } 20 | 21 | export default Index 22 | -------------------------------------------------------------------------------- /examples/data-fetch/src/pages/index/view.tsx: -------------------------------------------------------------------------------- 1 | import {View, Navigator} from '@tarojs/components' 2 | 3 | const IndexView = ({ stars }) => ( 4 | <> 5 | Tarojs has {stars} ⭐️ 6 | 11 | How about tarojs-plugin-platform-nextjs? 12 | 13 | 14 | ) 15 | 16 | export default IndexView 17 | -------------------------------------------------------------------------------- /examples/data-fetch/src/pages/stars/index.h5.tsx: -------------------------------------------------------------------------------- 1 | import {request} from '@tarojs/taro' 2 | 3 | export {default} from './view'; 4 | 5 | export async function getStaticProps() { 6 | const res = await request({ 7 | method: 'GET', 8 | url: 'https://api.github.com/repos/NervJS/tarojs-plugin-platform-nextjs' 9 | }) 10 | 11 | return { 12 | props: { 13 | stars: res.data.stargazers_count 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/data-fetch/src/pages/stars/index.tsx: -------------------------------------------------------------------------------- 1 | import {useEffect, useState} from 'react' 2 | import {request} from '@tarojs/taro' 3 | import IndexView from './view'; 4 | 5 | function TarojsPluginPlatformNextjsStarsView() { 6 | const [stars, setStars] = useState() 7 | 8 | useEffect(() => { 9 | (async function() { 10 | const res = await request({ 11 | method: 'GET', 12 | url: 'https://api.github.com/repos/NervJS/tarojs-plugin-platform-nextjs' 13 | }) 14 | setStars(res.data.stargazers_count) 15 | })() 16 | }, []) 17 | 18 | return 19 | } 20 | 21 | export default TarojsPluginPlatformNextjsStarsView 22 | -------------------------------------------------------------------------------- /examples/data-fetch/src/pages/stars/view.tsx: -------------------------------------------------------------------------------- 1 | import {View, Navigator} from '@tarojs/components' 2 | 3 | const TarojsPluginPlatformNextjsStarsView = ({ stars }) => ( 4 | <> 5 | tarojs-plugin-platform-nextjs has {stars} ⭐ 6 | 11 | I bet tarojs has more stars (?) 12 | 13 | 14 | ) 15 | 16 | export default TarojsPluginPlatformNextjsStarsView 17 | -------------------------------------------------------------------------------- /examples/data-fetch/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "commonjs", 5 | "removeComments": false, 6 | "preserveConstEnums": true, 7 | "moduleResolution": "node", 8 | "experimentalDecorators": true, 9 | "noImplicitAny": false, 10 | "allowSyntheticDefaultImports": true, 11 | "outDir": "lib", 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "strictNullChecks": true, 15 | "sourceMap": true, 16 | "baseUrl": ".", 17 | "rootDir": ".", 18 | "jsx": "react-jsx", 19 | "allowJs": true, 20 | "resolveJsonModule": true, 21 | "typeRoots": [ 22 | "node_modules/@types" 23 | ] 24 | }, 25 | "include": ["./src", "global.d.ts"], 26 | "compileOnSave": false 27 | } 28 | -------------------------------------------------------------------------------- /examples/dynamic-routing/README.md: -------------------------------------------------------------------------------- 1 | # 动态路由示例 2 | 3 | 这个例子展示如何使用动态路由。它包含两个动态路由: 4 | 5 | 1. pages/post/[id]/index.tsx 6 | * 例如,匹配 /post?id=my-example 7 | 2. pages/comment/[id]/[comment].tsx 8 | * 例如,匹配 /comment?id=my-example&comment=a-comment 9 | 10 | ## 执行 Next.js 11 | 12 | ```bash 13 | yarn dev:nextjs 14 | ``` 15 | 16 | ## 执行小程序 17 | 18 | ```bash 19 | yarn dev:swan 20 | ``` 21 | -------------------------------------------------------------------------------- /examples/dynamic-routing/babel.config.js: -------------------------------------------------------------------------------- 1 | // babel-preset-taro 更多选项和默认值: 2 | // https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md 3 | module.exports = { 4 | presets: [ 5 | ['taro', { 6 | framework: 'react', 7 | ts: true 8 | }] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /examples/dynamic-routing/config/dev.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"development"' 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/dynamic-routing/config/prod.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"production"' 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/dynamic-routing/global.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.png'; 4 | declare module '*.gif'; 5 | declare module '*.jpg'; 6 | declare module '*.jpeg'; 7 | declare module '*.svg'; 8 | declare module '*.css'; 9 | declare module '*.less'; 10 | declare module '*.scss'; 11 | declare module '*.sass'; 12 | declare module '*.styl'; 13 | 14 | declare namespace NodeJS { 15 | interface ProcessEnv { 16 | TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd' 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/dynamic-routing/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./dist", 3 | "projectname": "data", 4 | "description": "数据请求示例", 5 | "appid": "touristappid", 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": false, 9 | "postcss": false, 10 | "minified": false 11 | }, 12 | "compileType": "miniprogram" 13 | } 14 | -------------------------------------------------------------------------------- /examples/dynamic-routing/project.tt.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./", 3 | "projectname": "data", 4 | "appid": "testAppId", 5 | "setting": { 6 | "es6": false, 7 | "minified": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/dynamic-routing/src/app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | pages: [ 3 | 'pages/index/index', 4 | 'pages/post/index' 5 | ], 6 | window: { 7 | backgroundTextStyle: 'light', 8 | navigationBarBackgroundColor: '#fff', 9 | navigationBarTitleText: 'WeChat', 10 | navigationBarTextStyle: 'black' 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /examples/dynamic-routing/src/app.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 16px!important; 3 | margin: 8px!important; 4 | font-family: Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji!important; 5 | line-height: 1.5!important; 6 | } 7 | 8 | .paragraph { 9 | margin: 16px 0 16px; 10 | } 11 | 12 | .taro-nav { 13 | text-decoration: underline!important; 14 | } 15 | -------------------------------------------------------------------------------- /examples/dynamic-routing/src/app.ts: -------------------------------------------------------------------------------- 1 | import { Component } from 'react' 2 | import './app.scss' 3 | 4 | class App extends Component { 5 | 6 | componentDidMount () {} 7 | 8 | componentDidShow () {} 9 | 10 | componentDidHide () {} 11 | 12 | componentDidCatchError () {} 13 | 14 | // this.props.children 是将要会渲染的页面 15 | render () { 16 | return this.props.children 17 | } 18 | } 19 | 20 | export default App 21 | -------------------------------------------------------------------------------- /examples/dynamic-routing/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/dynamic-routing/src/pages/index/index.tsx: -------------------------------------------------------------------------------- 1 | import {View, Navigator} from '@tarojs/components' 2 | 3 | const Index = () => { 4 | const id = 'first' 5 | return ( 6 | <> 7 | Post: {id} 8 | 9 | 10 | 15 | First comment 16 | 17 | 18 | 19 | 24 | Second comment 25 | 26 | 27 | 28 | 29 | ) 30 | } 31 | 32 | export default Index 33 | -------------------------------------------------------------------------------- /examples/dynamic-routing/src/pages/post/[id]/[comment].tsx: -------------------------------------------------------------------------------- 1 | export {default} from '../view' 2 | 3 | export const getServerSideProps = async () => { 4 | return { 5 | props: {} 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/dynamic-routing/src/pages/post/[id]/index.tsx: -------------------------------------------------------------------------------- 1 | export {default} from '../view' 2 | 3 | export const getServerSideProps = async () => { 4 | return { 5 | props: {} 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/dynamic-routing/src/pages/post/index.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | navigationBarTitleText: '首页' 3 | } 4 | -------------------------------------------------------------------------------- /examples/dynamic-routing/src/pages/post/index.tsx: -------------------------------------------------------------------------------- 1 | export {default} from './view' 2 | -------------------------------------------------------------------------------- /examples/dynamic-routing/src/pages/post/view.tsx: -------------------------------------------------------------------------------- 1 | import {useRouter} from '@tarojs/taro' 2 | import {View} from '@tarojs/components' 3 | 4 | const PostView = () => { 5 | const {id, comment} = useRouter().params 6 | return ( 7 | <> 8 | Post: {id} 9 | Comment: {comment} 10 | 11 | ) 12 | } 13 | 14 | export default PostView 15 | -------------------------------------------------------------------------------- /examples/dynamic-routing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "commonjs", 5 | "removeComments": false, 6 | "preserveConstEnums": true, 7 | "moduleResolution": "node", 8 | "experimentalDecorators": true, 9 | "noImplicitAny": false, 10 | "allowSyntheticDefaultImports": true, 11 | "outDir": "lib", 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "strictNullChecks": true, 15 | "sourceMap": true, 16 | "baseUrl": ".", 17 | "rootDir": ".", 18 | "jsx": "react-jsx", 19 | "allowJs": true, 20 | "resolveJsonModule": true, 21 | "typeRoots": [ 22 | "node_modules/@types" 23 | ] 24 | }, 25 | "include": ["./src", "global.d.ts"], 26 | "compileOnSave": false 27 | } 28 | -------------------------------------------------------------------------------- /examples/reactions/README.md: -------------------------------------------------------------------------------- 1 | # ISR 示例 2 | 3 | 这个演示展示了 Next.js 的 ISR 功能,使用 GitHub Issues 作为数据源。 4 | 5 | ## 执行 Next.js 6 | 7 | ```bash 8 | export GITHUB_TOKEN= && yarn dev:nextjs 9 | ``` 10 | 11 | ## 执行小程序 12 | 13 | ```bash 14 | export GITHUB_TOKEN= && yarn dev:swan 15 | ``` 16 | -------------------------------------------------------------------------------- /examples/reactions/babel.config.js: -------------------------------------------------------------------------------- 1 | // babel-preset-taro 更多选项和默认值: 2 | // https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md 3 | module.exports = { 4 | presets: [ 5 | ['taro', { 6 | framework: 'react', 7 | ts: true 8 | }] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /examples/reactions/config/dev.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"development"' 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/reactions/config/prod.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"production"' 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/reactions/global.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.png'; 4 | declare module '*.gif'; 5 | declare module '*.jpg'; 6 | declare module '*.jpeg'; 7 | declare module '*.svg'; 8 | declare module '*.css'; 9 | declare module '*.less'; 10 | declare module '*.scss'; 11 | declare module '*.sass'; 12 | declare module '*.styl'; 13 | 14 | declare namespace NodeJS { 15 | interface ProcessEnv { 16 | TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd' 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/reactions/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./dist", 3 | "projectname": "data", 4 | "description": "数据请求示例", 5 | "appid": "touristappid", 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": false, 9 | "postcss": false, 10 | "minified": false 11 | }, 12 | "compileType": "miniprogram" 13 | } 14 | -------------------------------------------------------------------------------- /examples/reactions/project.tt.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./", 3 | "projectname": "data", 4 | "appid": "testAppId", 5 | "setting": { 6 | "es6": false, 7 | "minified": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/reactions/src/app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | pages: [ 3 | 'pages/index/index' 4 | ], 5 | window: { 6 | backgroundTextStyle: 'light', 7 | navigationBarBackgroundColor: '#fff', 8 | navigationBarTitleText: 'WeChat', 9 | navigationBarTextStyle: 'black' 10 | } 11 | }) 12 | -------------------------------------------------------------------------------- /examples/reactions/src/app.scss: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0!important; 3 | margin: 0!important; 4 | font-family: Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji!important; 5 | line-height: 1.5!important; 6 | } 7 | 8 | .taro-nav { 9 | display: inline-block!important; 10 | color: #0070f3!important; 11 | text-decoration: none!important; 12 | } 13 | 14 | .main { 15 | padding: 48px 16px; 16 | max-width: 640px; 17 | margin: 0 auto; 18 | font-size: 19px; 19 | } 20 | 21 | .h2 { 22 | margin: 20px 0; 23 | font-size: 24px; 24 | font-weight: bold; 25 | } 26 | 27 | .h3 { 28 | margin: 19px 0; 29 | font-size: 19px; 30 | font-weight: bold; 31 | } 32 | 33 | .line { 34 | font-size: 24px; 35 | text-align: center; 36 | } 37 | 38 | .emoji { 39 | display: inline; 40 | font-size: 32px; 41 | vertical-align: middle; 42 | } 43 | 44 | .strong { 45 | display: inline; 46 | font-weight: bold; 47 | } 48 | 49 | .ol { 50 | margin: 16px 0; 51 | } 52 | 53 | .li { 54 | position: relative; 55 | padding-left: 40px; 56 | margin: 8px 0; 57 | } 58 | 59 | .marker { 60 | position: absolute; 61 | left: 10px; 62 | top: 0; 63 | } 64 | -------------------------------------------------------------------------------- /examples/reactions/src/app.ts: -------------------------------------------------------------------------------- 1 | import { Component } from 'react' 2 | import './app.scss' 3 | 4 | class App extends Component { 5 | 6 | componentDidMount () {} 7 | 8 | componentDidShow () {} 9 | 10 | componentDidHide () {} 11 | 12 | componentDidCatchError () {} 13 | 14 | // this.props.children 是将要会渲染的页面 15 | render () { 16 | return this.props.children 17 | } 18 | } 19 | 20 | export default App 21 | -------------------------------------------------------------------------------- /examples/reactions/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/reactions/src/pages/index/index.config.ts: -------------------------------------------------------------------------------- 1 | export default definePageConfig({ 2 | navigationBarTitleText: '首页' 3 | }) 4 | -------------------------------------------------------------------------------- /examples/reactions/src/pages/index/index.h5.tsx: -------------------------------------------------------------------------------- 1 | import {request} from '@tarojs/taro' 2 | 3 | export {default} from './view'; 4 | 5 | export async function getStaticProps() { 6 | // { 7 | // "data": { 8 | // "repository": { 9 | // "issue": { 10 | // "reactionGroups": [ 11 | // { "content": "THUMBS_UP", "users": { "totalCount": 0 } }, 12 | // { "content": "THUMBS_DOWN", "users": { "totalCount": 0 } }, 13 | // { "content": "LAUGH", "users": { "totalCount": 0 } }, 14 | // { "content": "HOORAY", "users": { "totalCount": 0 } }, 15 | // { "content": "CONFUSED", "users": { "totalCount": 0 } }, 16 | // { "content": "HEART", "users": { "totalCount": 0 } }, 17 | // { "content": "ROCKET", "users": { "totalCount": 0 } }, 18 | // { "content": "EYES", "users": { "totalCount": 0 } } 19 | // ] 20 | // } 21 | // } 22 | // } 23 | // } 24 | const res = await request({ 25 | url: 'https://api.github.com/graphql', 26 | method: 'POST', 27 | header: { 28 | Authorization: `bearer ${process.env.GITHUB_TOKEN}`, 29 | }, 30 | data: { 31 | query: `query { 32 | repository(owner:"vercel", name:"reactions") { 33 | issue(number:1) { 34 | reactionGroups { 35 | content 36 | users(first: 0) { 37 | totalCount 38 | } 39 | } 40 | } 41 | } 42 | }` 43 | } 44 | }) 45 | 46 | const reactions = res.data.data.repository.issue.reactionGroups 47 | .map(item => item.users.totalCount) 48 | 49 | return { 50 | props: { 51 | reactions 52 | }, 53 | revalidate: 1 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /examples/reactions/src/pages/index/index.tsx: -------------------------------------------------------------------------------- 1 | import {useEffect, useState} from 'react' 2 | import {request} from '@tarojs/taro' 3 | import IndexView from './view'; 4 | 5 | function Index() { 6 | const [reactions, setReactions] = useState([]) 7 | 8 | useEffect(() => { 9 | (async function() { 10 | const res = await request({ 11 | url: 'https://api.github.com/graphql', 12 | method: 'POST', 13 | header: { 14 | Authorization: `bearer ${process.env.GITHUB_TOKEN}`, 15 | }, 16 | data: { 17 | query: `query { 18 | repository(owner:"vercel", name:"reactions") { 19 | issue(number:1) { 20 | reactionGroups { 21 | content 22 | users(first: 0) { 23 | totalCount 24 | } 25 | } 26 | } 27 | } 28 | }` 29 | } 30 | }) 31 | 32 | const reactions = res.data.data.repository.issue.reactionGroups 33 | .map(item => item.users.totalCount) 34 | setReactions(reactions) 35 | })() 36 | }, []) 37 | 38 | return 39 | } 40 | 41 | export default Index 42 | -------------------------------------------------------------------------------- /examples/reactions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "commonjs", 5 | "removeComments": false, 6 | "preserveConstEnums": true, 7 | "moduleResolution": "node", 8 | "experimentalDecorators": true, 9 | "noImplicitAny": false, 10 | "allowSyntheticDefaultImports": true, 11 | "outDir": "lib", 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "strictNullChecks": true, 15 | "sourceMap": true, 16 | "baseUrl": ".", 17 | "rootDir": ".", 18 | "jsx": "react-jsx", 19 | "allowJs": true, 20 | "resolveJsonModule": true, 21 | "typeRoots": [ 22 | "node_modules/@types" 23 | ] 24 | }, 25 | "include": ["./src", "global.d.ts"], 26 | "compileOnSave": false 27 | } 28 | -------------------------------------------------------------------------------- /examples/with-less/README.md: -------------------------------------------------------------------------------- 1 | # Less 示例 2 | 3 | Next.js 框架本身不支持 Less,插件内部依赖 [next-with-less](https://github.com/elado/next-with-less) 来对其进行支持。 4 | 5 | ## 执行 Next.js 6 | 7 | ```bash 8 | yarn dev:nextjs 9 | ``` 10 | 11 | ## 执行小程序 12 | 13 | ```bash 14 | yarn dev:swan 15 | ``` 16 | -------------------------------------------------------------------------------- /examples/with-less/babel.config.js: -------------------------------------------------------------------------------- 1 | // babel-preset-taro 更多选项和默认值: 2 | // https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md 3 | module.exports = { 4 | presets: [ 5 | ['taro', { 6 | framework: 'react', 7 | ts: true 8 | }] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /examples/with-less/config/dev.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"development"' 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/with-less/config/prod.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"production"' 4 | }, 5 | defineConstants: {}, 6 | mini: {}, 7 | h5: {} 8 | } 9 | -------------------------------------------------------------------------------- /examples/with-less/global.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.png'; 4 | declare module '*.gif'; 5 | declare module '*.jpg'; 6 | declare module '*.jpeg'; 7 | declare module '*.svg'; 8 | declare module '*.css'; 9 | declare module '*.less'; 10 | declare module '*.scss'; 11 | declare module '*.sass'; 12 | declare module '*.styl'; 13 | 14 | declare namespace NodeJS { 15 | interface ProcessEnv { 16 | TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd' 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/with-less/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./dist", 3 | "projectname": "data", 4 | "description": "数据请求示例", 5 | "appid": "touristappid", 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": false, 9 | "postcss": false, 10 | "minified": false 11 | }, 12 | "compileType": "miniprogram" 13 | } 14 | -------------------------------------------------------------------------------- /examples/with-less/project.tt.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./", 3 | "projectname": "data", 4 | "appid": "testAppId", 5 | "setting": { 6 | "es6": false, 7 | "minified": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/with-less/src/app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | pages: [ 3 | 'pages/index/index' 4 | ], 5 | window: { 6 | backgroundTextStyle: 'light', 7 | navigationBarBackgroundColor: '#fff', 8 | navigationBarTitleText: 'WeChat', 9 | navigationBarTextStyle: 'black' 10 | } 11 | }) 12 | -------------------------------------------------------------------------------- /examples/with-less/src/app.less: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0!important; 3 | margin: 0!important; 4 | font-family: Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji!important; 5 | line-height: 1.5!important; 6 | } 7 | -------------------------------------------------------------------------------- /examples/with-less/src/app.ts: -------------------------------------------------------------------------------- 1 | import { Component } from 'react' 2 | import './app.less' 3 | 4 | class App extends Component { 5 | 6 | componentDidMount () {} 7 | 8 | componentDidShow () {} 9 | 10 | componentDidHide () {} 11 | 12 | componentDidCatchError () {} 13 | 14 | // this.props.children 是将要会渲染的页面 15 | render () { 16 | return this.props.children 17 | } 18 | } 19 | 20 | export default App 21 | -------------------------------------------------------------------------------- /examples/with-less/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/with-less/src/pages/index/index.config.ts: -------------------------------------------------------------------------------- 1 | export default definePageConfig({ 2 | navigationBarTitleText: '首页' 3 | }) 4 | -------------------------------------------------------------------------------- /examples/with-less/src/pages/index/index.h5.tsx: -------------------------------------------------------------------------------- 1 | export {default} from './view'; 2 | 3 | export async function getStaticProps() { 4 | return { 5 | props: {}, 6 | revalidate: 1 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/with-less/src/pages/index/index.module.less: -------------------------------------------------------------------------------- 1 | // mixins 2 | .bordered { 3 | border-top: dotted 1px black; 4 | border-bottom: solid 2px black; 5 | } 6 | 7 | .a { 8 | color: #111; 9 | .bordered(); 10 | } 11 | 12 | // functions 13 | @base: #f04615; 14 | @width: 1; 15 | 16 | .functions { 17 | width: percentage(@width); 18 | color: saturate(@base, 5%); 19 | background-color: spin(lighten(@base, 25%), 8); 20 | } 21 | -------------------------------------------------------------------------------- /examples/with-less/src/pages/index/index.tsx: -------------------------------------------------------------------------------- 1 | import IndexView from './view'; 2 | 3 | function Index() { 4 | return 5 | } 6 | 7 | export default Index 8 | -------------------------------------------------------------------------------- /examples/with-less/src/pages/index/view.tsx: -------------------------------------------------------------------------------- 1 | import {View} from '@tarojs/components' 2 | import styles from './index.module.less'; 3 | 4 | const IndexView = () => ( 5 | <> 6 | 混合(Mixins) 7 | 函数(Functions) 8 | 9 | ); 10 | 11 | export default IndexView 12 | -------------------------------------------------------------------------------- /examples/with-less/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "commonjs", 5 | "removeComments": false, 6 | "preserveConstEnums": true, 7 | "moduleResolution": "node", 8 | "experimentalDecorators": true, 9 | "noImplicitAny": false, 10 | "allowSyntheticDefaultImports": true, 11 | "outDir": "lib", 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "strictNullChecks": true, 15 | "sourceMap": true, 16 | "baseUrl": ".", 17 | "rootDir": ".", 18 | "jsx": "react-jsx", 19 | "allowJs": true, 20 | "resolveJsonModule": true, 21 | "typeRoots": [ 22 | "node_modules/@types" 23 | ] 24 | }, 25 | "include": ["./src", "global.d.ts"], 26 | "compileOnSave": false 27 | } 28 | -------------------------------------------------------------------------------- /examples/with-postcss/README.md: -------------------------------------------------------------------------------- 1 | # Postcss 示例 2 | 3 | 使用本地 postcss 插件。 4 | 5 | ## 执行 Next.js 6 | 7 | ```bash 8 | yarn dev:nextjs 9 | ``` 10 | 11 | ## 执行小程序 12 | 13 | ```bash 14 | yarn dev:swan 15 | ``` 16 | -------------------------------------------------------------------------------- /examples/with-postcss/babel.config.js: -------------------------------------------------------------------------------- 1 | // babel-preset-taro 更多选项和默认值: 2 | // https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md 3 | module.exports = { 4 | presets: [ 5 | ['taro', { 6 | framework: 'react', 7 | ts: true 8 | }] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /examples/with-postcss/config/dev.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"development"' 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/with-postcss/config/prod.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"production"' 4 | }, 5 | defineConstants: {}, 6 | mini: {}, 7 | h5: {} 8 | } 9 | -------------------------------------------------------------------------------- /examples/with-postcss/global.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.png'; 4 | declare module '*.gif'; 5 | declare module '*.jpg'; 6 | declare module '*.jpeg'; 7 | declare module '*.svg'; 8 | declare module '*.css'; 9 | declare module '*.less'; 10 | declare module '*.scss'; 11 | declare module '*.sass'; 12 | declare module '*.styl'; 13 | 14 | declare namespace NodeJS { 15 | interface ProcessEnv { 16 | TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd' 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/with-postcss/postcss-plugins/red-color.js: -------------------------------------------------------------------------------- 1 | const postcss = require('postcss') 2 | 3 | module.exports = () => { 4 | return { 5 | postcssPlugin: 'postcss-red-color', 6 | Once(css) { 7 | css.walkRules(rule => { 8 | const decl = { prop: 'color', value: 'red' } 9 | rule.append(decl) 10 | }) 11 | } 12 | } 13 | } 14 | 15 | module.exports.postcss = true 16 | -------------------------------------------------------------------------------- /examples/with-postcss/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./dist", 3 | "projectname": "data", 4 | "description": "数据请求示例", 5 | "appid": "touristappid", 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": false, 9 | "postcss": false, 10 | "minified": false 11 | }, 12 | "compileType": "miniprogram" 13 | } 14 | -------------------------------------------------------------------------------- /examples/with-postcss/project.tt.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "./", 3 | "projectname": "data", 4 | "appid": "testAppId", 5 | "setting": { 6 | "es6": false, 7 | "minified": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/with-postcss/src/app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | pages: [ 3 | 'pages/index/index' 4 | ], 5 | window: { 6 | backgroundTextStyle: 'light', 7 | navigationBarBackgroundColor: '#fff', 8 | navigationBarTitleText: 'WeChat', 9 | navigationBarTextStyle: 'black' 10 | } 11 | }) 12 | -------------------------------------------------------------------------------- /examples/with-postcss/src/app.less: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0!important; 3 | margin: 0!important; 4 | font-family: Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji!important; 5 | line-height: 1.5!important; 6 | } 7 | -------------------------------------------------------------------------------- /examples/with-postcss/src/app.ts: -------------------------------------------------------------------------------- 1 | import { Component } from 'react' 2 | import './app.less' 3 | 4 | class App extends Component { 5 | 6 | componentDidMount () {} 7 | 8 | componentDidShow () {} 9 | 10 | componentDidHide () {} 11 | 12 | componentDidCatchError () {} 13 | 14 | // this.props.children 是将要会渲染的页面 15 | render () { 16 | return this.props.children 17 | } 18 | } 19 | 20 | export default App 21 | -------------------------------------------------------------------------------- /examples/with-postcss/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/with-postcss/src/pages/index/index.config.ts: -------------------------------------------------------------------------------- 1 | export default definePageConfig({ 2 | navigationBarTitleText: '首页' 3 | }) 4 | -------------------------------------------------------------------------------- /examples/with-postcss/src/pages/index/index.h5.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './view'; 2 | 3 | export async function getStaticProps() { 4 | return { 5 | props: {}, 6 | revalidate: 1 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/with-postcss/src/pages/index/index.module.less: -------------------------------------------------------------------------------- 1 | // mixins 2 | .bordered { 3 | border-top: dotted 1px black; 4 | border-bottom: solid 2px black; 5 | } 6 | 7 | .a { 8 | color: #111; 9 | .bordered(); 10 | } 11 | 12 | // functions 13 | @base: #f04615; 14 | @width: 1; 15 | 16 | .functions { 17 | width: percentage(@width); 18 | color: saturate(@base, 5%); 19 | background-color: spin(lighten(@base, 25%), 8); 20 | } 21 | -------------------------------------------------------------------------------- /examples/with-postcss/src/pages/index/index.tsx: -------------------------------------------------------------------------------- 1 | import IndexView from './view'; 2 | 3 | function Index() { 4 | return 5 | } 6 | 7 | export default Index 8 | -------------------------------------------------------------------------------- /examples/with-postcss/src/pages/index/view.tsx: -------------------------------------------------------------------------------- 1 | import {View} from '@tarojs/components' 2 | import styles from './index.module.less'; 3 | 4 | const IndexView = () => ( 5 | <> 6 | 混合(Mixins) 7 | 函数(Functions) 8 | 9 | ); 10 | 11 | export default IndexView 12 | -------------------------------------------------------------------------------- /examples/with-postcss/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "commonjs", 5 | "removeComments": false, 6 | "preserveConstEnums": true, 7 | "moduleResolution": "node", 8 | "experimentalDecorators": true, 9 | "noImplicitAny": false, 10 | "allowSyntheticDefaultImports": true, 11 | "outDir": "lib", 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "strictNullChecks": true, 15 | "sourceMap": true, 16 | "baseUrl": ".", 17 | "rootDir": ".", 18 | "jsx": "react-jsx", 19 | "allowJs": true, 20 | "resolveJsonModule": true, 21 | "typeRoots": [ 22 | "node_modules/@types" 23 | ] 24 | }, 25 | "include": ["./src", "global.d.ts"], 26 | "compileOnSave": false 27 | } 28 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | testRegex: '(\\.|/)(test|spec)\\.[jt]sx?$' 6 | } 7 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "useWorkspaces": true, 4 | "packages": [ 5 | "packages/*" 6 | ], 7 | "command": { 8 | "publish": { 9 | "npmClient": "npm", 10 | "registry": "https://registry.npmjs.org/" 11 | } 12 | }, 13 | "version": "2.1.6" 14 | } 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "taror-project", 3 | "private": true, 4 | "workspaces": [ 5 | "packages/*" 6 | ], 7 | "scripts": { 8 | "lerna": "lerna", 9 | "build": "lerna run build --stream", 10 | "test": "jest" 11 | }, 12 | "engines": { 13 | "node": ">=12.22.0" 14 | }, 15 | "devDependencies": { 16 | "@testing-library/react": "^12.1.5", 17 | "@types/jest": "^27.5.0", 18 | "@types/node": "^18.6.3", 19 | "@types/react": "^17.0.14", 20 | "@types/react-dom": "^17.0.14", 21 | "@typescript-eslint/eslint-plugin": "^5.30.6", 22 | "@typescript-eslint/parser": "^5.30.6", 23 | "eslint": "^8.20.0", 24 | "eslint-plugin-react": "^7.30.1", 25 | "eslint-plugin-react-hooks": "^4.6.0", 26 | "jest": "^28.1.0", 27 | "jest-environment-jsdom": "^28.1.1", 28 | "lerna": "^4.0.0", 29 | "tree-kill": "^1.2.2", 30 | "ts-jest": "^28.0.2", 31 | "typescript": "^4.7.4" 32 | }, 33 | "resolutions": { 34 | "@types/react": "^17.0.14", 35 | "@types/react-dom": "^17.0.14", 36 | "@types/history": "^4.7.9" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/components/.dumi/theme/components/layout/index.scss: -------------------------------------------------------------------------------- 1 | .__dumi-default-mobile-content>article { 2 | min-width: auto; 3 | width: 100%; 4 | } 5 | -------------------------------------------------------------------------------- /packages/components/.dumi/theme/components/subMenu/index.scss: -------------------------------------------------------------------------------- 1 | .__dumi-default-menu-inner ul li a { 2 | line-height: 1.4; 3 | padding: 12px 0; 4 | } 5 | -------------------------------------------------------------------------------- /packages/components/.umirc.ts: -------------------------------------------------------------------------------- 1 | import {defineConfig} from 'dumi' 2 | 3 | const BASE_PATH = '/tarojs-plugin-ssr' 4 | 5 | export default defineConfig({ 6 | title: 'taror', 7 | base: BASE_PATH, 8 | outputPath: 'docs-dist', 9 | publicPath: `${BASE_PATH}/`, 10 | define: { 11 | BASE_PATH 12 | }, 13 | extraBabelPlugins: [ 14 | [ 15 | 'import', 16 | { 17 | libraryName: '@taror/components', 18 | libraryDirectory: 'src', 19 | style: true 20 | } 21 | ] 22 | ], 23 | themeConfig: { 24 | carrier: 'SyMind', 25 | hd: { 26 | rules: [{ mode: 'none' }] 27 | } 28 | } 29 | }) 30 | -------------------------------------------------------------------------------- /packages/components/README.md: -------------------------------------------------------------------------------- 1 | # 基于 React 的 Taro3 组件实现 2 | 3 | ## 文档 4 | 5 | https://nervjs.github.io/ssr/ 6 | 7 | ## 安装 8 | 9 | ```bash 10 | npm install @taror/components 11 | ``` 12 | 13 | ```bash 14 | yarn add @taror/components 15 | ``` 16 | -------------------------------------------------------------------------------- /packages/components/index-style-only.js: -------------------------------------------------------------------------------- 1 | function pascalCase(name) { 2 | return name.charAt(0).toUpperCase() + name.slice(1).replace(/-(\w)/g, (m, n) => n.toUpperCase()) 3 | } 4 | 5 | // Just import style for https://github.com/ant-design/ant-design/issues/3745 6 | const req = require.context('./src', true, /^\.\/[^_][\w-]+\/style\/index\.tsx?$/) 7 | 8 | req.keys().forEach(mod => { 9 | let v = req(mod) 10 | if (v && v.default) { 11 | v = v.default 12 | } 13 | const match = mod.match(/^\.\/([^_][\w-]+)\/index\.tsx?$/) 14 | if (match && match[1]) { 15 | if (match[1] === 'message' || match[1] === 'notification') { 16 | // message & notification should not be capitalized 17 | exports[match[1]] = v 18 | } else { 19 | exports[pascalCase(match[1])] = v 20 | } 21 | } 22 | }) 23 | 24 | module.exports = exports 25 | -------------------------------------------------------------------------------- /packages/components/index.js: -------------------------------------------------------------------------------- 1 | require('./index-style-only') 2 | 3 | module.exports = require('./src') 4 | -------------------------------------------------------------------------------- /packages/components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@taror/components", 3 | "version": "2.1.5", 4 | "description": "React-based Taro3 components implementation", 5 | "license": "MIT", 6 | "files": [ 7 | "dist", 8 | "lib", 9 | "es" 10 | ], 11 | "main": "lib/index.js", 12 | "module": "es/index.js", 13 | "unpkg": "dist/taror.min.js", 14 | "typings": "lib/index.d.ts", 15 | "scripts": { 16 | "prepublishOnly": "yarn build", 17 | "start": "dumi dev", 18 | "docs:build": "dumi build", 19 | "docs:deploy": "gh-pages -f -d docs-dist", 20 | "deploy": "yarn run docs:build && yarn run docs:deploy", 21 | "build": "yarn compile && yarn dist", 22 | "compile": "yarn clean && taror-tools run compile", 23 | "dist": "taror-tools run dist", 24 | "clean": "taror-tools run clean && rm -rf es lib coverage dist report.html" 25 | }, 26 | "devDependencies": { 27 | "@taror/tools": "^0.0.6", 28 | "@umijs/plugin-sass": "^1.1.1", 29 | "babel-plugin-import": "^1.13.5", 30 | "dumi": "^1.1.46", 31 | "dumi-theme-mobile": "^1.1.24", 32 | "gh-pages": "^4.0.0" 33 | }, 34 | "dependencies": { 35 | "@babel/runtime": "^7.0.0", 36 | "@react-spring/web": "9.5.2", 37 | "@use-gesture/react": "^10.2.0", 38 | "classnames": "^2.2.5", 39 | "lodash": "^4.17.21", 40 | "react-is": "^18.1.0", 41 | "swiper": "^6.8.0", 42 | "weui": "^1.1.2" 43 | }, 44 | "peerDependencies": { 45 | "react": ">=16.9.0", 46 | "react-dom": ">=16.9.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/components/src/_util/children/toArray.ts: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {isFragment} from 'react-is' 3 | 4 | export interface Option { 5 | keepEmpty?: boolean; 6 | } 7 | 8 | export default function toArray( 9 | children: React.ReactNode, 10 | option: Option = {} 11 | ): React.ReactElement[] { 12 | let ret: React.ReactElement[] = [] 13 | 14 | React.Children.forEach(children, (child: any) => { 15 | if ((child === undefined || child === null) && !option.keepEmpty) { 16 | return 17 | } 18 | 19 | if (Array.isArray(child)) { 20 | ret = ret.concat(toArray(child)) 21 | } else if (isFragment(child) && child.props) { 22 | ret = ret.concat(toArray(child.props.children, option)) 23 | } else { 24 | ret.push(child) 25 | } 26 | }) 27 | 28 | return ret 29 | } 30 | -------------------------------------------------------------------------------- /packages/components/src/_util/dom/requestIdleCallback.ts: -------------------------------------------------------------------------------- 1 | export const requestIdleCallback = (typeof globalThis !== 'undefined') && globalThis.requestIdleCallback 2 | || function (cb: IdleRequestCallback): number { 3 | const start = Date.now() 4 | return setTimeout(function () { 5 | cb({ 6 | didTimeout: false, 7 | timeRemaining: function () { 8 | return Math.max(0, 50 - (Date.now() - start)) 9 | } 10 | }) 11 | }, 1) as unknown as number 12 | } 13 | 14 | export const cancelIdleCallback = (typeof globalThis !== 'undefined') && globalThis.cancelIdleCallback 15 | || function (id: number) { 16 | return clearTimeout(id) 17 | } 18 | -------------------------------------------------------------------------------- /packages/components/src/_util/hooks/useMergedState.ts: -------------------------------------------------------------------------------- 1 | import {useState, useRef, useEffect} from 'react' 2 | 3 | export default function useMergedState( 4 | defaultStateValue?: T | (() => T), 5 | option?: { 6 | defaultValue?: T | (() => T); 7 | value?: T; 8 | onChange?: (value: T, prevValue?: T) => void; 9 | postState?: (value?: T) => T; 10 | } 11 | ): [R, (value: T) => void] { 12 | const {defaultValue, value, onChange, postState} = option || {} 13 | const [innerValue, setInnerValue] = useState(() => { 14 | if (value !== undefined) { 15 | return value 16 | } 17 | if (defaultValue !== undefined) { 18 | return defaultValue instanceof Function 19 | ? defaultValue() 20 | : defaultValue 21 | } 22 | 23 | return defaultStateValue instanceof Function 24 | ? defaultStateValue() 25 | : defaultStateValue 26 | }) 27 | 28 | let mergedValue = value !== undefined ? value : innerValue 29 | if (postState) { 30 | mergedValue = postState(mergedValue) 31 | } 32 | 33 | function triggerChange(newValue: T) { 34 | setInnerValue(newValue) 35 | if (mergedValue !== newValue && onChange) { 36 | onChange(newValue, mergedValue) 37 | } 38 | } 39 | 40 | // Effect of reset value to `undefined` 41 | const firstRenderRef = useRef(true) 42 | useEffect(() => { 43 | if (firstRenderRef.current) { 44 | firstRenderRef.current = false 45 | 46 | return 47 | } 48 | 49 | if (value === undefined) { 50 | setInnerValue(value) 51 | } 52 | }, [value]) 53 | 54 | return [(mergedValue as unknown) as R, triggerChange] 55 | } 56 | -------------------------------------------------------------------------------- /packages/components/src/block/index.tsx: -------------------------------------------------------------------------------- 1 | import {Fragment} from 'react' 2 | 3 | export default Fragment 4 | -------------------------------------------------------------------------------- /packages/components/src/button/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .hover { 2 | opacity: .2; 3 | background-color: #888; 4 | } 5 | 6 | .Favor, 7 | .noFavor:after { 8 | position: static; 9 | content: none; 10 | } 11 | 12 | .Favor { 13 | border: 1px solid #e6e6e6; 14 | border-radius: 59px; 15 | background-image: url(https://b.bdstatic.com/searchbox/icms/searchbox/img/demo_followed.png); 16 | background-size: 21px 21px; 17 | background-repeat: no-repeat; 18 | background-position: 33% 50%; 19 | } 20 | 21 | .noFavor { 22 | background-color: #3388ff; 23 | color: #fff; 24 | background-image: url(https://b.bdstatic.com/searchbox/icms/searchbox/img/demo_follow.png); 25 | background-size: 21px 21px; 26 | background-repeat: no-repeat; 27 | background-position: 35% 50%; 28 | border: 1px solid #e6e6e6; 29 | border-radius: 59px; 30 | } 31 | -------------------------------------------------------------------------------- /packages/components/src/button/index.md: -------------------------------------------------------------------------------- 1 | # Button 按钮 2 | 3 | 按钮用于开始一个即时操作。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/button/style/index.scss: -------------------------------------------------------------------------------- 1 | .weui-btn:after { 2 | pointer-events: none; 3 | } 4 | -------------------------------------------------------------------------------- /packages/components/src/button/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/form/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .switch-scroll { 2 | margin: 17px!important; 3 | } 4 | 5 | .block { 6 | margin: 0 17px; 7 | padding: 17px 0; 8 | display: block; 9 | background-color: #fff; 10 | } 11 | 12 | .switch-text { 13 | vertical-align: 2px; 14 | } 15 | 16 | .radio-item { 17 | padding: 15px 0; 18 | margin: 0 15px; 19 | } 20 | 21 | .checkbox-item { 22 | padding: 15px 0; 23 | margin: 0 15px; 24 | display: block; 25 | } 26 | 27 | .input { 28 | height: 51px; 29 | margin: 0; 30 | } 31 | 32 | .plh { 33 | line-height: 18px; 34 | color: #CCC; 35 | font-family: PingFangSC-Regular; 36 | } 37 | 38 | .slider { 39 | margin: 3px; 40 | } 41 | 42 | .ipt { 43 | height: 51px; 44 | margin: 0 17px; 45 | } 46 | -------------------------------------------------------------------------------- /packages/components/src/form/formContext.ts: -------------------------------------------------------------------------------- 1 | import {createContext} from 'react' 2 | 3 | export interface FormContextProps { 4 | subscribe(cb: () => void): void 5 | collect(name: string | undefined, value: any) 6 | } 7 | 8 | const FormContext = createContext(null) 9 | 10 | export default FormContext 11 | -------------------------------------------------------------------------------- /packages/components/src/form/index.md: -------------------------------------------------------------------------------- 1 | # Form 表单 2 | 3 | 表单,将 Form 组件内用户输入的 Switch、Input、Checkbox、Slider、Radio、Picker 提交。当表单中 formType 为 submit 时,点击的 Button 组件会将表单组件中的 value 值进行提交,需要在表单组件中加上 name 来作为 key 。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/form/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | -------------------------------------------------------------------------------- /packages/components/src/form/useField.ts: -------------------------------------------------------------------------------- 1 | import {useContext, useEffect} from 'react' 2 | import FormContext from './formContext' 3 | 4 | function useField(name: string | undefined, value: any): void { 5 | const formContext = useContext(FormContext) 6 | 7 | useEffect(() => { 8 | if (!formContext) { 9 | return 10 | } 11 | const unsubscribe = formContext.subscribe(() => { 12 | formContext.collect(name, value) 13 | }) 14 | return unsubscribe 15 | }, [name, value]) 16 | } 17 | 18 | export default useField 19 | -------------------------------------------------------------------------------- /packages/components/src/icon/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .icon-area { 2 | margin-top: 15px; 3 | } 4 | 5 | .icon-item { 6 | display: inline-block; 7 | flex-direction: column; 8 | width: 80px; 9 | height: 95px; 10 | margin: 7px; 11 | text-align: center; 12 | 13 | justify-content: center; 14 | } 15 | 16 | .icon-text { 17 | width: 80px; 18 | margin-top: 15px; 19 | word-break: break-all; 20 | } 21 | -------------------------------------------------------------------------------- /packages/components/src/icon/index.md: -------------------------------------------------------------------------------- 1 | # Icon 图标 2 | 3 | 图片组件。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/icon/index.tsx: -------------------------------------------------------------------------------- 1 | import React, {forwardRef} from 'react' 2 | import classNames from 'classnames' 3 | import type {TaroBaseProps} from '../_util/typings' 4 | import useTaroBaseEvents from '../_util/hooks/useTaroBaseEvents' 5 | 6 | export interface IconProps extends TaroBaseProps { 7 | /** 8 | * 图标 9 | */ 10 | type?: string 11 | 12 | /** 13 | * icon 的大小(单位:px) 14 | */ 15 | size?: number 16 | 17 | /** 18 | * icon 的颜色 19 | */ 20 | color?: string 21 | } 22 | 23 | const Icon: React.ForwardRefRenderFunction = ({ 24 | style, 25 | className, 26 | type, 27 | size = 30, 28 | color, 29 | ...rest 30 | }, ref) => { 31 | const props = useTaroBaseEvents(rest) 32 | 33 | const mergedStyle: React.CSSProperties = Object.assign({}, style, { 34 | fontSize: size ? `${size}px` : undefined, 35 | color 36 | }) 37 | 38 | return ( 39 | 48 | ) 49 | } 50 | 51 | export default forwardRef(Icon) 52 | -------------------------------------------------------------------------------- /packages/components/src/icon/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | -------------------------------------------------------------------------------- /packages/components/src/image/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .wrap { 2 | margin-top: 20px; 3 | } 4 | .image-area { 5 | width: 100%; 6 | height: 155px; 7 | } 8 | 9 | .bottom-description { 10 | height: auto; 11 | margin: 17px; 12 | } 13 | 14 | .back-ground { 15 | background-color: #e6e6e6; 16 | } 17 | 18 | .image-custom { 19 | width: 100%; 20 | margin-bottom: -4px; 21 | } 22 | -------------------------------------------------------------------------------- /packages/components/src/image/index.md: -------------------------------------------------------------------------------- 1 | # Image 图片 2 | 3 | 图片,支持 JPG、PNG、GIF、BMP、WEBP 等格式。image 组件默认宽度 300px 、高度 225px 。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/image/style/index.scss: -------------------------------------------------------------------------------- 1 | .taro-img { 2 | overflow: hidden; 3 | display: inline-block; 4 | width: 300px; 5 | height: 225px; 6 | 7 | &__content { 8 | height: 100%; 9 | width: 100%; 10 | background-repeat: no-repeat; 11 | background-size: contain; 12 | } 13 | 14 | &__scale-to-fill { 15 | background-size: 100% 100%; 16 | background-position: 0% 0%; 17 | } 18 | 19 | &__aspect-fit { 20 | background-size: contain; 21 | background-position: center center; 22 | } 23 | 24 | &__aspect-fill { 25 | background-size: cover; 26 | background-position: center center; 27 | } 28 | 29 | &__width-fix { 30 | background-size: 100% 100%; 31 | background-position: 0% 0%; 32 | } 33 | 34 | &__height-fix { 35 | background-size: 100% 100%; 36 | background-position: 0% 0%; 37 | } 38 | 39 | &__top { 40 | background-position: top center; 41 | } 42 | 43 | &__bottom { 44 | background-position: bottom center; 45 | } 46 | 47 | &__center { 48 | background-position: center center; 49 | } 50 | 51 | &__left { 52 | background-position: center left; 53 | } 54 | 55 | &__right { 56 | background-position: center right; 57 | } 58 | 59 | &__top-left { 60 | background-position: top left; 61 | } 62 | 63 | &__top-right { 64 | background-position: top right; 65 | } 66 | 67 | &__bottom-left { 68 | background-position: bottom left; 69 | } 70 | 71 | &__bottom-right { 72 | background-position: bottom right; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /packages/components/src/image/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/input/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .normalInput { 2 | height: 51px; 3 | margin: 0 17px; 4 | } 5 | 6 | .textarea { 7 | min-height: 51px; 8 | margin: 0 17px; 9 | padding: 10px; 10 | background-color: #f8f8f8; 11 | } 12 | -------------------------------------------------------------------------------- /packages/components/src/input/index.md: -------------------------------------------------------------------------------- 1 | # Input 输入框 2 | 3 | 输入框。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/input/style/index.scss: -------------------------------------------------------------------------------- 1 | .taro-input { 2 | overflow: hidden; 3 | position: relative; 4 | display: block; 5 | height: 14px; 6 | min-height: 14px; 7 | white-space: nowrap; 8 | text-overflow: clip; 9 | color: #333; 10 | 11 | &_content { 12 | position: relative; 13 | display: flex; 14 | align-items: center; 15 | width: 100%; 16 | height: 100%; 17 | font-size: inherit; 18 | text-overflow: inherit; 19 | } 20 | 21 | &_placeholder { 22 | position: absolute; 23 | top: 50%; 24 | left: 0; 25 | font-size: inherit; 26 | color: #ccc; 27 | transform: translateY(-50%); 28 | } 29 | 30 | &_main { 31 | font-size: inherit; 32 | font-weight: inherit; 33 | color: inherit; 34 | background: transparent; 35 | border: none; 36 | outline: none; 37 | text-align: inherit; 38 | text-overflow: inherit; 39 | font-family: inherit; 40 | padding: inherit; 41 | width: 100%; 42 | white-space: nowrap; 43 | overflow: hidden; 44 | z-index: 1; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/components/src/input/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/label/index.tsx: -------------------------------------------------------------------------------- 1 | import React, {forwardRef} from 'react' 2 | import type {TaroBaseProps} from '../_util/typings' 3 | import useTaroBaseEvents from '../_util/hooks/useTaroBaseEvents' 4 | 5 | export interface LabelProps extends TaroBaseProps { 6 | /** 7 | * 绑定控件的 id 8 | */ 9 | for?: string 10 | 11 | /** 12 | * 标签内容 13 | */ 14 | children?: React.ReactNode 15 | } 16 | 17 | const Label: React.ForwardRefRenderFunction = ({ 18 | for: htmlFor, 19 | children, 20 | ...rest 21 | }, ref) => { 22 | const handles = useTaroBaseEvents(rest) 23 | 24 | return ( 25 | 32 | ) 33 | } 34 | 35 | export default forwardRef(Label) 36 | -------------------------------------------------------------------------------- /packages/components/src/label/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | -------------------------------------------------------------------------------- /packages/components/src/mask/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import classNames from 'classnames' 3 | 4 | export interface MaskProps { 5 | /** 6 | * 类名 7 | */ 8 | className?: string 9 | 10 | /** 11 | * 是否可见 12 | * 13 | * @default true 14 | */ 15 | visible?: boolean 16 | 17 | /** 18 | * 背景是否透明 19 | * 20 | * @default false 21 | */ 22 | transparent?: boolean 23 | 24 | /** 25 | * 蒙层内容 26 | */ 27 | children?: React.ReactNode 28 | 29 | /** 30 | * 点击蒙层自身触发 31 | */ 32 | onClick?: () => void 33 | } 34 | 35 | const Mask: React.FC = ({className, visible = true, transparent = false, children, onClick}) => { 36 | if (!visible) { 37 | return null 38 | } 39 | 40 | return ( 41 |
42 |
49 | {children} 50 |
51 | ) 52 | } 53 | 54 | export default Mask 55 | -------------------------------------------------------------------------------- /packages/components/src/mask/style/index.scss: -------------------------------------------------------------------------------- 1 | .taro-mask { 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | display: block; 6 | width: 100%; 7 | height: 100%; 8 | z-index: 1000; 9 | 10 | &_button { 11 | position: absolute; 12 | top: 0; 13 | right: 0; 14 | left: 0; 15 | bottom: 0; 16 | background: #000; 17 | 18 | &-transparent { 19 | background: transparent; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/components/src/mask/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/modal/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | -------------------------------------------------------------------------------- /packages/components/src/navigator/demos/demo1.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {View, Button, Navigator} from '@taror/components' 3 | 4 | declare const BASE_PATH: string 5 | 6 | const App: React.FC = () => ( 7 | 8 | 17 | 18 | ) 19 | 20 | export default App 21 | -------------------------------------------------------------------------------- /packages/components/src/navigator/demos/demo2.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {View, Button, Navigator} from '@taror/components' 3 | 4 | const App: React.FC = () => ( 5 | 6 | 7 | 16 | 17 | 18 | ) 19 | 20 | export default App 21 | -------------------------------------------------------------------------------- /packages/components/src/navigator/index.md: -------------------------------------------------------------------------------- 1 | # Navigator 页面导航 2 | 3 | 页面链接,控制小程序的跳转,既可在当前小程序内部进行跳转,也可跳转至其他小程序。navigator 的子节点背景色应为透明色。 4 | 5 | ## 示例 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/components/src/navigator/style/index.scss: -------------------------------------------------------------------------------- 1 | .taro-nav { 2 | display: block; 3 | width: auto; 4 | height: auto; 5 | color: inherit; 6 | } 7 | 8 | .navigator-hover { 9 | opacity: .7; 10 | background-color: rgba(0, 0, 0, .1) 11 | } 12 | -------------------------------------------------------------------------------- /packages/components/src/navigator/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/picker-view-column/index.md: -------------------------------------------------------------------------------- 1 | # PickerViewColumn 滚动选择器子项 2 | 3 | 可嵌页面的滚动选择器子项。仅可放置于 PickerView 中,其孩子节点的高度会自动设置成与 picker-view 的选中框的高度一致。 4 | 5 | ## 示例 6 | 7 | 参见 PickerView 示例内容。 8 | -------------------------------------------------------------------------------- /packages/components/src/picker-view-column/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export interface PickerViewColumnProps { 4 | children?: React.ReactNode 5 | } 6 | 7 | const PickerViewColumn: React.FC = ({children}) => <>{children} 8 | 9 | export default PickerViewColumn 10 | -------------------------------------------------------------------------------- /packages/components/src/picker-view-column/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | -------------------------------------------------------------------------------- /packages/components/src/picker-view/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .item { 2 | text-align: center; 3 | } 4 | 5 | .selected-date { 6 | margin: 30px; 7 | text-align: center; 8 | } 9 | -------------------------------------------------------------------------------- /packages/components/src/picker-view/demos/demo1.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { PickerView, PickerViewColumn, View } from '@taror/components' 3 | import '@taror/components/src/picker-view/style' 4 | import './demo1.scss' 5 | 6 | const date = new Date() 7 | const years: number[] = [] 8 | const months: number[] = [] 9 | const days: number[] = [] 10 | 11 | for (let i = 1990; i <= date.getFullYear(); i++) { 12 | years.push(i) 13 | } 14 | 15 | for (let i = 1; i <= 12; i++) { 16 | months.push(i) 17 | } 18 | 19 | for (let i = 1; i <= 31; i++) { 20 | days.push(i) 21 | } 22 | 23 | const App: React.FC = () => { 24 | const [value, setValue] = useState([years.length - 1, 1, 1]) 25 | 26 | return ( 27 | <> 28 | 29 | {years[value[0]]}年{months[value[1]]}月{days[value[2]]}日 30 | 31 | { 39 | if (event.detail.value) { 40 | setValue(event.detail.value) 41 | } 42 | }} 43 | > 44 | 45 | {years.map(year => {year}年)} 46 | 47 | 48 | {months.map(month => {month}月)} 49 | 50 | 51 | {days.map(day => {day}日)} 52 | 53 | 54 | 55 | ) 56 | } 57 | 58 | export default App 59 | -------------------------------------------------------------------------------- /packages/components/src/picker-view/index.md: -------------------------------------------------------------------------------- 1 | # PickerView 滚动选择器 2 | 3 | 可嵌页面的滚动选择器。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/picker-view/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/picker/constant.js: -------------------------------------------------------------------------------- 1 | export const TOP = 102 2 | 3 | export const LINE_HEIGHT = 34 4 | 5 | export const MASK_HEIGHT = LINE_HEIGHT * 7 6 | -------------------------------------------------------------------------------- /packages/components/src/picker/date.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author zhongxin 3 | * @description 日期选择器相关函数 4 | * 5 | */ 6 | 7 | /** 8 | * 校验日期合法性,返回合法性和日期数组 9 | * 10 | * @param {String} date 11 | * @param {String} start 12 | * @param {String} end 13 | * @returns 14 | */ 15 | function verifyDate(date) { 16 | if (!date) return false 17 | date = new Date(date.replace(/-/g, '/')) 18 | return isNaN(date.getMonth()) ? false : date 19 | } 20 | 21 | /** 22 | * 获取当月最大天数 23 | * 24 | * @param {Number} year 25 | * @param {Number} month 26 | * @returns 27 | */ 28 | function getMaxDay(year, month) { 29 | if (month === 4 || month === 6 || month === 9 || month === 11) return 30 30 | if (month === 2) { 31 | if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) return 29 32 | else return 28 33 | } 34 | return 31 35 | } 36 | export { 37 | verifyDate, 38 | getMaxDay 39 | } 40 | -------------------------------------------------------------------------------- /packages/components/src/picker/style/index.js: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/picker/style/index.scss: -------------------------------------------------------------------------------- 1 | .weui-picker, .weui-picker__hd { 2 | font-size: 12px; 3 | } 4 | -------------------------------------------------------------------------------- /packages/components/src/preview/index.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState} from 'react' 2 | import Mask from '../mask' 3 | import Swiper from '../swiper' 4 | import SwiperItem from '../swiper-item' 5 | 6 | interface PreviewProps { 7 | /** 8 | * 当前显示图片的链接,不填则默认为 urls 的第一张 9 | */ 10 | defaultCurrent?: string 11 | 12 | /** 13 | * 需要预览的图片链接列表 14 | */ 15 | urls: string[] 16 | 17 | /** 18 | * 关闭时触发 19 | */ 20 | onClose?: () => void; 21 | } 22 | 23 | const Preview: React.FC = ({defaultCurrent, urls, onClose}) => { 24 | const [current, setCurrent] = useState(() => { 25 | if (defaultCurrent) { 26 | const index = urls.indexOf(defaultCurrent) 27 | return index !== -1 ? index : 0 28 | } 29 | return 0 30 | }) 31 | 32 | return ( 33 | 34 | { 38 | setCurrent(event.detail.current) 39 | }} 40 | > 41 | {urls.map((url, index) => ( 42 | 46 | 47 | 48 | ))} 49 | 50 | 51 |
52 | {current + 1}/{urls.length} 53 |
54 |
55 | ) 56 | } 57 | 58 | export default Preview 59 | -------------------------------------------------------------------------------- /packages/components/src/preview/style/index.scss: -------------------------------------------------------------------------------- 1 | .taro-preview { 2 | &_img { 3 | width: 100%; 4 | max-width: 100%; 5 | max-height: 100%; 6 | object-fit: contain; 7 | } 8 | 9 | &_swiper { 10 | position: absolute; 11 | top: 50%; 12 | width: 100%; 13 | height: fit-content; 14 | transform: translateY(-50%); 15 | 16 | &-item { 17 | display: flex; 18 | align-items: center; 19 | } 20 | } 21 | 22 | &_pagination { 23 | position: absolute; 24 | left: 20px; 25 | bottom: 30px; 26 | font-size: 16px; 27 | color: #fff; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/components/src/preview/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | 4 | // style dependencies 5 | import '../../mask/style' 6 | import '../../swiper/style' 7 | -------------------------------------------------------------------------------- /packages/components/src/progress/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .progress, 2 | .inner-progress { 3 | margin: 35px 23px; 4 | } 5 | 6 | .inner-progress .progress-bar { 7 | border-radius: 25px; 8 | } 9 | .inner-progress .progress-inner-bar { 10 | border-radius: 25px; 11 | } 12 | -------------------------------------------------------------------------------- /packages/components/src/progress/index.md: -------------------------------------------------------------------------------- 1 | # Progress 进度条 2 | 3 | 进度条。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/progress/style/index.scss: -------------------------------------------------------------------------------- 1 | .weui-progress { 2 | &__bar { 3 | overflow: hidden; 4 | } 5 | 6 | &__inner-bar { 7 | width: 100%; 8 | height: 100%; 9 | transform-origin: left; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/components/src/progress/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/rich-text/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .rich-text { 2 | font-size: 16px; 3 | margin-left: 17px; 4 | } 5 | 6 | .p { 7 | color: #4F99FB; 8 | line-height: 48px; 9 | } 10 | 11 | .taro-scroll-view { 12 | width: 100%; 13 | height: 215px; 14 | background-color: #FFF; 15 | box-sizing: border-box; 16 | line-height: 30px; 17 | } 18 | .cont { 19 | width: 100%; 20 | height: 100%; 21 | white-space: pre; 22 | padding: 10px 16px; 23 | color: #999; 24 | } 25 | -------------------------------------------------------------------------------- /packages/components/src/rich-text/index.md: -------------------------------------------------------------------------------- 1 | # RichText 富文本 2 | 3 | 富文本。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/rich-text/style/index.scss: -------------------------------------------------------------------------------- 1 | .taro-rich-text__selectable { 2 | user-select: auto; 3 | } 4 | -------------------------------------------------------------------------------- /packages/components/src/rich-text/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/scroll-view/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .scroll-view { 2 | height: 166px; 3 | white-space: nowrap; 4 | } 5 | 6 | .color-a, 7 | .color-b, 8 | .color-c { 9 | line-height: 166px; 10 | text-align: center; 11 | font-size: 16px; 12 | color: #fff; 13 | } 14 | 15 | .color-a { 16 | background-color: #5B9FFF; 17 | } 18 | .color-b { 19 | background-color: #85B8FF; 20 | } 21 | .color-c { 22 | background-color: #ADCFFF; 23 | } 24 | 25 | .row-view { 26 | display: inline-block !important; 27 | width: 100%; 28 | height: 166px; 29 | line-height: 166px; 30 | } 31 | 32 | .page-section-btns { 33 | display: flex; 34 | justify-content: space-around; 35 | align-items: center; 36 | margin: 0 23px; 37 | } 38 | 39 | .page-section-btns > div { 40 | flex: 1; 41 | height: 28px; 42 | width: 100px; 43 | display: flex; 44 | align-items: center; 45 | justify-content: space-around; 46 | color: #6895FF; 47 | border: 1px solid #38F; 48 | border-radius: 5px; 49 | margin: 10px 14px; 50 | } 51 | 52 | .scroll-to-top { 53 | border-right: 1px solid #ddd; 54 | } 55 | 56 | .next-page { 57 | border-left: 1px solid #ddd; 58 | } 59 | 60 | 61 | .horizontal-rolling { 62 | height: 250px; 63 | } 64 | 65 | .arrange { 66 | display: flex; 67 | } 68 | 69 | .scroll-item { 70 | padding: 17px 17px; 71 | height: 250px; 72 | } 73 | 74 | .scroll-image { 75 | width: 120px; 76 | height: 130px; 77 | border-radius: 15px; 78 | } 79 | -------------------------------------------------------------------------------- /packages/components/src/scroll-view/index.md: -------------------------------------------------------------------------------- 1 | # ScrollView 可滚动视图区域 2 | 3 | 可滚动视图区域,可实现横向滚动和竖向滚动。使用竖向滚动时,需要给定该组件一个固定高度,可以通过 CSS 设置 height 。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/scroll-view/style/index.scss: -------------------------------------------------------------------------------- 1 | .taro-scroll { 2 | -webkit-overflow-scrolling: auto; 3 | } 4 | 5 | .taro-scroll::-webkit-scrollbar { 6 | display: none; 7 | } 8 | 9 | .taro-scroll-view { 10 | overflow: hidden; 11 | } 12 | 13 | .taro-scroll-view__scroll-x { 14 | overflow-x: scroll; 15 | overflow-y: hidden; 16 | } 17 | 18 | .taro-scroll-view__scroll-y { 19 | overflow-x: hidden; 20 | overflow-y: scroll; 21 | } 22 | -------------------------------------------------------------------------------- /packages/components/src/scroll-view/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/style/index.scss: -------------------------------------------------------------------------------- 1 | @import '~weui/dist/style/weui.min.css'; 2 | 3 | body, html { 4 | width: 100%; 5 | margin: 0; 6 | padding: 0; 7 | font-family: STHeiti SC, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, "sans-serif"; 8 | user-select: none; 9 | } 10 | 11 | ::-webkit-scrollbar { 12 | display: none; 13 | } 14 | 15 | * { 16 | margin: 0; 17 | padding: 0; 18 | } 19 | -------------------------------------------------------------------------------- /packages/components/src/style/index.ts: -------------------------------------------------------------------------------- 1 | import './index.scss' 2 | -------------------------------------------------------------------------------- /packages/components/src/swiper-item/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import classNames from 'classnames' 3 | import {TaroBaseAttributes, TaroMouseEventHandler} from '../_util/typings' 4 | import { createTaroMouseEvent } from '../_util/taroEvent' 5 | 6 | export interface SwiperItemProps extends TaroBaseAttributes { 7 | 8 | /** 9 | * 该 swiper-item 的标识符 10 | */ 11 | itemId?: string 12 | 13 | /** 14 | * 内容 15 | */ 16 | children?: React.ReactNode 17 | 18 | /** 19 | * 触摸后马上离开 20 | */ 21 | onClick?: TaroMouseEventHandler 22 | } 23 | 24 | const SwiperItem: React.FC = ({className, itemId, children, onClick, ...rest}) => { 25 | return ( 26 |
{ 30 | const taroEvent = createTaroMouseEvent('tap', reactEvent) 31 | onClick?.(taroEvent) 32 | }} 33 | {...rest} 34 | > 35 | {children} 36 |
37 | ) 38 | } 39 | 40 | export default SwiperItem 41 | -------------------------------------------------------------------------------- /packages/components/src/swiper-item/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | -------------------------------------------------------------------------------- /packages/components/src/swiper/index.md: -------------------------------------------------------------------------------- 1 | # Swiper 视图容器 2 | 3 | 滑块视图容器。内部只允许使用 SwiperItem 组件描述滑块内容,否则会导致未定义的行为。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/swiper/style/index.scss: -------------------------------------------------------------------------------- 1 | .taro-swiper { 2 | &__dots { 3 | position: absolute; 4 | font-size: 0; 5 | z-index: 1; 6 | 7 | &-horizontal { 8 | bottom: 8px; 9 | left: 50%; 10 | text-align: center; 11 | white-space: nowrap; 12 | transform: translate(-50%); 13 | 14 | .taro-swiper__dot { 15 | margin-right: 8px; 16 | } 17 | 18 | .taro-swiper__dot:last-child { 19 | margin-right: 0; 20 | } 21 | } 22 | 23 | &-vertical { 24 | top: 50%; 25 | right: 8px; 26 | text-align: right; 27 | transform: translateY(-50%); 28 | 29 | .taro-swiper__dot { 30 | display: block; 31 | margin-bottom: 9px; 32 | } 33 | 34 | .taro-swiper__dot:last-child { 35 | margin-bottom: 0; 36 | } 37 | } 38 | } 39 | 40 | &__dot { 41 | width: 5px; 42 | height: 5px; 43 | display: inline-block; 44 | border-radius: 50%; 45 | background: rgba(0, 0, 0, .3); 46 | transition-timing-function: ease; 47 | transition-property: background-color; 48 | will-change: transform; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/components/src/swiper/style/index.ts: -------------------------------------------------------------------------------- 1 | import 'swiper/swiper.scss' 2 | import '../../style/index.scss' 3 | import './index.scss' 4 | -------------------------------------------------------------------------------- /packages/components/src/switch/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .init-switch { 2 | margin: 14px 0 14px 17px; 3 | vertical-align: middle; 4 | } 5 | 6 | .init-switch-after { 7 | margin: 14px 0 14px 50px; 8 | vertical-align: middle; 9 | } 10 | 11 | .switch-text { 12 | vertical-align: middle; 13 | } 14 | -------------------------------------------------------------------------------- /packages/components/src/switch/index.md: -------------------------------------------------------------------------------- 1 | # Switch 开关选择器 2 | 3 | 开关选择器。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/switch/style/index.scss: -------------------------------------------------------------------------------- 1 | .weui-agree__checkbox { 2 | width: 22px; 3 | height: 22px; 4 | 5 | &::before { 6 | font-size: 22px; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/components/src/switch/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/text/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .text-box { 2 | margin: 17px; 3 | } 4 | 5 | .text-block { 6 | display: block; 7 | height: 24px; 8 | overflow: hidden; 9 | white-space: nowrap; 10 | text-overflow: ellipsis; 11 | } 12 | -------------------------------------------------------------------------------- /packages/components/src/text/demos/demo1.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { View, Text } from '@taror/components' 3 | import './demo1.scss' 4 | 5 | const text1 = '智能 小程序(nbsp,根据字体设置的空格大小)' 6 | const text2 = '智能 小程序(ensp,中文字符空格一半大小)' 7 | const text3 = '智能 小程序(emsp,中文字符空格大小)' 8 | 9 | const App: React.FC = () => ( 10 | 11 | 12 | 13 | 默认 14 | selectable 15 | 16 | 20 | 百度智能小程序(文本支持长按选择) 21 | 22 | 23 | 24 | 25 | 设置显示4个连续空格 26 | space 27 | 28 | 29 | {text1} 30 | {text2} 31 | {text3} 32 | 33 | 34 | 35 | ) 36 | 37 | export default App 38 | -------------------------------------------------------------------------------- /packages/components/src/text/index.md: -------------------------------------------------------------------------------- 1 | # Text 文本 2 | 3 | 文本元素。 4 | 5 | ## 示例 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/components/src/text/index.tsx: -------------------------------------------------------------------------------- 1 | import React, {forwardRef} from 'react' 2 | import classNames from 'classnames' 3 | import type {TaroBaseProps} from '../_util/typings' 4 | import useTaroBaseEvents from '../_util/hooks/useTaroBaseEvents' 5 | 6 | export interface TextProps extends TaroBaseProps { 7 | /** 8 | * 显示连续空格 9 | * @default false 10 | */ 11 | space?: false | 'ensp' | 'emsp' | 'nbsp' 12 | 13 | /** 14 | * 文本是否可选 15 | * @default false 16 | */ 17 | selectable?: boolean 18 | 19 | /** 20 | * 文本内容 21 | */ 22 | children?: React.ReactNode 23 | } 24 | 25 | const Text: React.ForwardRefRenderFunction = ({ 26 | className, 27 | space = false, 28 | selectable = false, 29 | children, 30 | ...rest 31 | }, ref) => { 32 | const props = useTaroBaseEvents(rest) 33 | 34 | if (typeof children === 'string') { 35 | if (space === 'nbsp') { 36 | children = children.replace(/ /g, ' ') 37 | } else if (space === 'ensp') { 38 | children = children.replace(/ /g, ' ') 39 | } else if (space === 'emsp') { 40 | children = children.replace(/ /g, ' ') 41 | } 42 | } 43 | 44 | return ( 45 | 54 | {children} 55 | 56 | ) 57 | } 58 | 59 | export default forwardRef(Text) 60 | -------------------------------------------------------------------------------- /packages/components/src/text/style/index.scss: -------------------------------------------------------------------------------- 1 | .taro-text_selectable { 2 | user-select: text; 3 | } 4 | -------------------------------------------------------------------------------- /packages/components/src/text/style/index.ts: -------------------------------------------------------------------------------- 1 | import '../../style/index.scss' 2 | import './index.scss' 3 | -------------------------------------------------------------------------------- /packages/components/src/textarea/demos/demo1.scss: -------------------------------------------------------------------------------- 1 | .taro-textarea { 2 | width: 100%; 3 | padding: 17px; 4 | } 5 | -------------------------------------------------------------------------------- /packages/components/src/textarea/demos/demo1.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { View, Textarea } from '@taror/components' 3 | import './demo1.scss' 4 | 5 | const App: React.FC = () => { 6 | const handleInput = e => { 7 | console.log('input - e:', e) 8 | } 9 | 10 | return ( 11 | 12 | 13 | 14 | 输入区高度自适应 15 | auto-height 16 | 17 |