diff --git a/.babel-preset.js b/.babel-preset.js index ec786a0795..8dd10d83b4 100644 --- a/.babel-preset.js +++ b/.babel-preset.js @@ -24,6 +24,9 @@ const plugins = [ '@babel/plugin-transform-runtime', { regenerator: isDocsBuild, + useESModules: isESBuild, + // https://github.com/babel/babel/issues/10261 + version: require('@babel/runtime/package.json').version, }, ], // Plugins that allow to reduce the target bundle size @@ -36,13 +39,6 @@ const plugins = [ removeImport: isUMDBuild, }, ], - // A plugin for react-static - isDocsBuild && [ - 'universal-import', - { - disableWarnings: true, - }, - ], // A plugin for removal of debug in production builds isLibBuild && [ 'filter-imports', @@ -76,4 +72,15 @@ module.exports = () => ({ plugins: [['istanbul', { include: ['src'] }]], }, }, + overrides: [ + // A workaround to avoid collisions between "babel-plugin-dynamic-import-node" & "universal-import" + { + test: /react-static-routes.js/, + plugins: [ + ['universal-import', { disableWarnings: true }], + '@babel/plugin-transform-modules-commonjs', + ], + presets: [['@babel/env', { modules: false }]], + }, + ], }) diff --git a/.circleci/config.yml b/.circleci/config.yml index 08958dffb9..302f79bb34 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,54 +1,87 @@ -version: 2 +version: 2.1 + general: branches: ignore: - gh-pages + +docker_defaults: &docker_defaults + docker: + - image: circleci/node:12-browsers + working_directory: ~/project/semantic-ui-react + +restore_node_modules: &restore_node_modules + restore_cache: + name: Restore node_modules cache + keys: + - v3-node-{{ .Branch }}-{{ checksum "yarn.lock" }} + - v3-node-{{ .Branch }}- + - v3-node- + jobs: - build: - docker: - - image: circleci/node:8-browsers - environment: - TZ: "/usr/share/zoneinfo/America/Los_Angeles" + bootstrap: + <<: *docker_defaults steps: - - run: - name: Update yarn - command: | - # remove default yarn - sudo rm -rf $(dirname $(which yarn))/yarn* - # download latest - rm -rf ~/.yarn - curl -o- -L https://yarnpkg.com/install.sh | bash - echo 'export PATH="${PATH}:${HOME}/.yarn/bin"' >> $BASH_ENV - checkout - # because we don't invoke npm (we use yarn) we need to add npm bin to PATH manually - - run: - name: Add npm bin to PATH - command: echo 'export PATH="${PATH}:$(npm bin)"' >> $BASH_ENV - - restore_cache: - keys: - - v2-dependencies-{{ checksum "yarn.lock" }} + - *restore_node_modules - run: name: Install Dependencies - command: yarn + command: yarn install --frozen-lockfile - save_cache: - key: v2-dependencies-{{ checksum "yarn.lock" }} + name: Save yarn cache + key: v3-yarn-{{ .Branch }}-{{ checksum "yarn.lock" }} paths: - - ~/.cache/yarn - - run: - name: Lint TypeScript - command: yarn tsd:lint - - run: - name: Test TypeScript - command: yarn tsd:test + - .cache/yarn + - save_cache: + name: Save node_modules cache + key: v3-node-{{ .Branch }}-{{ checksum "yarn.lock" }} + paths: + - node_modules/ - run: - name: Lint JavaScript - command: yarn lint + name: Remove node_modules to cleanup workspace + command: rm -r node_modules/ + - persist_to_workspace: + root: ~/project + paths: + - semantic-ui-react + + test: + <<: *docker_defaults + steps: + - attach_workspace: + at: ~/project + - *restore_node_modules - run: name: Test JavaScript command: yarn test + - run: + name: Report coverage + command: bash <(curl -s https://codecov.io/bash) + - run: + name: Test TypeScript + command: yarn tsd:test - run: name: Test UMD bundle command: yarn test:umd + + lint: + <<: *docker_defaults + steps: + - attach_workspace: + at: ~/project + - *restore_node_modules - run: - name: Report coverage - command: bash <(curl -s https://codecov.io/bash) + name: Lint + command: yarn lint + +workflows: + version: 2 + main: + jobs: + - bootstrap + - test: + requires: + - bootstrap + - lint: + requires: + - bootstrap diff --git a/.eslintignore b/.eslintignore index b501af3790..5053239b57 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ +bundle-size/dist/* coverage/* dist/* docs/dist/* diff --git a/.eslintrc b/.eslintrc index f83bbc8246..14d66ad96c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,4 +1,5 @@ { + "root": true, "parser": "babel-eslint", "extends": ["airbnb", "prettier"], "env": { @@ -15,11 +16,14 @@ "no-multi-spaces": ["error", { "ignoreEOLComments": true }], "no-return-assign": ["error", "except-parens"], "no-underscore-dangle": "off", - "padded-blocks": ["error", { - "blocks": "never", - "switches": "never", - "classes": "never" - }], + "padded-blocks": [ + "error", + { + "blocks": "never", + "switches": "never", + "classes": "never" + } + ], "prefer-destructuring": "off", "jsx-a11y/alt-text": "warn", "jsx-a11y/anchor-is-valid": "off", @@ -28,6 +32,8 @@ "jsx-a11y/label-has-associated-control": "warn", "jsx-a11y/no-static-element-interactions": "warn", "jsx-a11y/role-has-required-aria-props": "warn", + "import/named": "off", + "import/no-cycle": "off", "import/no-dynamic-require": "off", "import/no-extraneous-dependencies": "off", "import/no-unresolved": "off", @@ -36,11 +42,32 @@ "react/button-has-type": "off", "react/destructuring-assignment": "off", "react/forbid-prop-types": "off", - "react/jsx-one-expression-per-line": "off", - "react/jsx-filename-extension": [2, { "extensions": [".js"] }], + "react/jsx-curly-newline": "off", + "react/jsx-one-expression-per-line": "off", + "react/jsx-filename-extension": ["error", { "extensions": [".js", ".tsx"] }], + "react/jsx-props-no-spreading": "off", "react/jsx-wrap-multilines": "off", + "react/prefer-stateless-function": "off", "react/no-unused-prop-types": "off", "react/sort-comp": "off", - "react/require-default-props":"off" - } + "react/state-in-constructor": "off", + "react/require-default-props": "off" + }, + "overrides": [ + { + "files": ["**/*.ts", "**/*.tsx"], + "parser": "@typescript-eslint/parser", + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "plugins": ["@typescript-eslint"], + "rules": { + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-empty-interface": "off" + } + } + ] } diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 148685fcc0..71487771cf 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -60,7 +60,7 @@ cd Semantic-UI-React yarn ``` ->Note, we use `yarn` because `npm` has unfortunately become unreliable. Get it [here][16]. +>Note: we use `yarn` and advise you do too while contributing. Get it [here](https://yarnpkg.com/). You can use `npm install / npm ci` but we don't include a `package-lock.json` in the repository, so you may end up with slightly out of sync dependencies. Add our repo as a git remote so you can pull/rebase your fork with our latest updates: @@ -516,7 +516,7 @@ Label.propTypes = { ### Examples ->This section is lacking in instruction as the the docs are set to be overhauled (PRs welcome!). +>This section is lacking in instruction as the docs are set to be overhauled (PRs welcome!). Usage examples for a component live in `docs/src/examples`. The examples follow the SUI doc site examples. diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index 1dfebfc380..0000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,33 +0,0 @@ -# Number of days of inactivity before an issue becomes stale -daysUntilStale: 180 - -# Number of days of inactivity before a stale issue is closed -daysUntilClose: 180 - -# Issues with these labels will never be considered stale -exemptLabels: - - pinned - - security - -# Label to use when marking an issue as stale -staleLabel: stale - -# Comment to post when marking an issue as stale. Set to `false` to disable -markComment: > - There has been no activity in this thread for 180 days. While we care about - every issue and we’d love to see this fixed, the core team’s time is - limited so we have to focus our attention on the issues that are most - pressing. Therefore, we will likely not be able to get to this one. - - - However, PRs for this issue will of course be accepted and welcome! - - - If there is no more activity in the next 180 days, this issue will be closed - automatically for housekeeping. To prevent this, simply leave a reply here. - Thanks! - -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: > - This issue will be closed due to lack of activity for 12 months. If you’d - like this to be reopened, just leave a comment; we do monitor them! diff --git a/.github/workflows/pr-health.yml b/.github/workflows/pr-health.yml new file mode 100644 index 0000000000..ff78e0d197 --- /dev/null +++ b/.github/workflows/pr-health.yml @@ -0,0 +1,14 @@ +name: PR Health +on: + pull_request: + types: [opened, labeled, unlabeled, synchronize] + +jobs: + label: + runs-on: ubuntu-latest + steps: + - uses: mheap/github-action-required-labels@v1 + with: + mode: exactly + count: 1 + labels: "PR: Breaking Change :boom:, PR: New Feature :rocket:, PR: Bug Fix :bug:, PR: Docs :memo:, PR: Internal :house:" diff --git a/.github/workflows/size-limit.yml b/.github/workflows/size-limit.yml new file mode 100644 index 0000000000..1897cbd5da --- /dev/null +++ b/.github/workflows/size-limit.yml @@ -0,0 +1,35 @@ +name: Bundle Size +on: + pull_request: + branches: + - master + +jobs: + size: + runs-on: ubuntu-latest + env: + CI_JOB_NUMBER: 1 + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v1 + with: + node-version: 12.x + + - name: Cache node_modules + uses: actions/cache@v1 + id: yarn-cache-node-modules + with: + path: node_modules + key: ${{ runner.os }}-yarn-cache-node-modules-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn-cache-node-modules- + + - name: Yarn install + if: steps.yarn-cache-node-modules.outputs.cache-hit != 'true' + run: yarn install --frozen-lockfile + + - uses: andresz1/size-limit-action@v1.4.0 + with: + build_script: build:size + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.prettierrc.json b/.prettierrc.json index 14bedecbad..75c5a1bfc7 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -14,12 +14,6 @@ "parser": "json" } }, - { - "files": "*.{ts,tsx}", - "options": { - "semi": true - } - }, { "files": "docs/src/examples/**/*.js", "options": { diff --git a/.size-limit.js b/.size-limit.js new file mode 100644 index 0000000000..0ed05cb77e --- /dev/null +++ b/.size-limit.js @@ -0,0 +1,5 @@ +module.exports = require('glob') + .sync('bundle-size/dist/*.size.js', { + cwd: __dirname, + }) + .map((file) => ({ path: file, gzip: false })) diff --git a/CHANGELOG.md b/CHANGELOG.md index 580a10ff0c..12659382b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,44 @@ # Change Log +## [v1.0.0](https://github.com/Semantic-Org/Semantic-UI-React/tree/v1.0.0) (2020-07-21) + +[Full Changelog](https://github.com/Semantic-Org/Semantic-UI-React/compare/v0.88.2...v1.0.0) + +**Merged pull requests:** + +- docs: remove knobs usage [\#3988](https://github.com/Semantic-Org/Semantic-UI-React/pull/3988) ([layershifter](https://github.com/layershifter)) +- chore\(Dropdown\): remove deprecated lifecycle methods [\#3986](https://github.com/Semantic-Org/Semantic-UI-React/pull/3986) ([layershifter](https://github.com/layershifter)) +- chore: use `react-intersection-observer` in docs to improve perf [\#3985](https://github.com/Semantic-Org/Semantic-UI-React/pull/3985) ([reefman001](https://github.com/reefman001)) +- chore\(Transition\): remove deprecated lifecycle methods [\#3982](https://github.com/Semantic-Org/Semantic-UI-React/pull/3982) ([layershifter](https://github.com/layershifter)) +- chore\(Sticky\): remove usage of deprecated lifecycle methods [\#3974](https://github.com/Semantic-Org/Semantic-UI-React/pull/3974) ([layershifter](https://github.com/layershifter)) +- chore\(Visibility\): remove usage of deprecated lifecycle methods [\#3973](https://github.com/Semantic-Org/Semantic-UI-React/pull/3973) ([layershifter](https://github.com/layershifter)) +- chore\(TransitionGroup\): remove deprecated lifecycle methods [\#3970](https://github.com/Semantic-Org/Semantic-UI-React/pull/3970) ([layershifter](https://github.com/layershifter)) +- chore\(Search\): replace deprecated lifecycle methods [\#3968](https://github.com/Semantic-Org/Semantic-UI-React/pull/3968) ([layershifter](https://github.com/layershifter)) +- chore: use ModernAutoControlled component [\#3967](https://github.com/Semantic-Org/Semantic-UI-React/pull/3967) ([layershifter](https://github.com/layershifter)) +- chore\(TransitionablePortal\): remove usage of UNSAFE\_\* methods [\#3966](https://github.com/Semantic-Org/Semantic-UI-React/pull/3966) ([layershifter](https://github.com/layershifter)) +- fix\(customProptypes\): add a check for Element existance [\#3965](https://github.com/Semantic-Org/Semantic-UI-React/pull/3965) ([layershifter](https://github.com/layershifter)) +- docs\(README.md\): fix formatting [\#3958](https://github.com/Semantic-Org/Semantic-UI-React/pull/3958) ([klunico](https://github.com/klunico)) +- docs\(VisibilityExampleUpdateOn\): Correcting Typo [\#3952](https://github.com/Semantic-Org/Semantic-UI-React/pull/3952) ([mattorton](https://github.com/mattorton)) +- fix\(Input\): add 'inputMode' attribute to input [\#3916](https://github.com/Semantic-Org/Semantic-UI-React/pull/3916) ([RoyalHunt](https://github.com/RoyalHunt)) + +## [v0.88.2](https://github.com/Semantic-Org/Semantic-UI-React/tree/v0.88.2) (2019-12-08) +[Full Changelog](https://github.com/Semantic-Org/Semantic-UI-React/compare/v0.88.1...v0.88.2) + +**Merged pull requests:** + +- chore: update husky hooks [\#3859](https://github.com/Semantic-Org/Semantic-UI-React/pull/3859) ([levithomason](https://github.com/levithomason)) +- chore: remove stale bot [\#3858](https://github.com/Semantic-Org/Semantic-UI-React/pull/3858) ([levithomason](https://github.com/levithomason)) +- fix\(Search\): use result.id for SearchResult key [\#3848](https://github.com/Semantic-Org/Semantic-UI-React/pull/3848) ([unbug](https://github.com/unbug)) +- docs\(misc\): fix typos [\#3837](https://github.com/Semantic-Org/Semantic-UI-React/pull/3837) ([yuuyu00](https://github.com/yuuyu00)) +- fix\(FeedSummary\): add missing space around content [\#3836](https://github.com/Semantic-Org/Semantic-UI-React/pull/3836) ([ridvankaradag](https://github.com/ridvankaradag)) +- feat\(FormField\): make form field error accessible [\#3822](https://github.com/Semantic-Org/Semantic-UI-React/pull/3822) ([aoelen](https://github.com/aoelen)) +- docs: fix minor grammar and punctuation errors [\#3818](https://github.com/Semantic-Org/Semantic-UI-React/pull/3818) ([anupamasok](https://github.com/anupamasok)) +- docs: update warning about using yarn [\#3816](https://github.com/Semantic-Org/Semantic-UI-React/pull/3816) ([chrisbrainerd](https://github.com/chrisbrainerd)) +- docs: update grammar/wording for tab pane shorthand [\#3801](https://github.com/Semantic-Org/Semantic-UI-React/pull/3801) ([spencerbyw](https://github.com/spencerbyw)) +- docs\(MenuExampleHeaderVertical\): fix onClick handler [\#3799](https://github.com/Semantic-Org/Semantic-UI-React/pull/3799) ([Suzi004](https://github.com/Suzi004)) +- chore\(lib\): add ModernAutoControlledComponent [\#3776](https://github.com/Semantic-Org/Semantic-UI-React/pull/3776) ([layershifter](https://github.com/layershifter)) +- feat\(Search\): custom category layout renderer [\#3672](https://github.com/Semantic-Org/Semantic-UI-React/pull/3672) ([PrincessMadMath](https://github.com/PrincessMadMath)) + ## [v0.88.1](https://github.com/Semantic-Org/Semantic-UI-React/tree/v0.88.1) (2019-09-09) [Full Changelog](https://github.com/Semantic-Org/Semantic-UI-React/compare/v0.88.0...v0.88.1) @@ -16,6 +55,7 @@ **Merged pull requests:** +- feat\(TextArea\): export StrictTextAreaProps typing [\#3846](https://github.com/Semantic-Org/Semantic-UI-React/pull/3846) ([chrisbull](https://github.com/chrisbull)) - docs\(CodeSandbox\): fix paths for images in exported examples [\#3758](https://github.com/Semantic-Org/Semantic-UI-React/pull/3758) ([layershifter](https://github.com/layershifter)) - fix\(typings\): add missing `StrictMenuProps` type export [\#3755](https://github.com/Semantic-Org/Semantic-UI-React/pull/3755) ([b-smets](https://github.com/b-smets)) - docs\(Popup\): add example for `delay` prop in Popup [\#3754](https://github.com/Semantic-Org/Semantic-UI-React/pull/3754) ([SandipNirmal](https://github.com/SandipNirmal)) @@ -149,7 +189,7 @@ - fix\(Dropdown\): retain focus on the input if the Dropdown receives a click [\#3422](https://github.com/Semantic-Org/Semantic-UI-React/pull/3422) ([jongsue](https://github.com/jongsue)) - docs\(Portal\): fix controlled Portal usage [\#3420](https://github.com/Semantic-Org/Semantic-UI-React/pull/3420) ([Fabianopb](https://github.com/Fabianopb)) - feat\(Accordion\): add `icon` shorthand for AccordionTitle [\#3417](https://github.com/Semantic-Org/Semantic-UI-React/pull/3417) ([sako9](https://github.com/sako9)) -- fix\(Icon\): update typings for `corner` prop [\#3393](https://github.com/Semantic-Org/Semantic-UI-React/pull/3393) ([areading314](https://github.com/areading314)) +- feat\(Flag\): export names in typings [\#2957](https://github.com/Semantic-Org/Semantic-UI-React/pull/2957) ([layershifter](https://github.com/layershifter)) - docs\(Sticky\): add warning about erratic behavior inside `Sidebar.Pushable` [\#2936](https://github.com/Semantic-Org/Semantic-UI-React/pull/2936) ([brambow](https://github.com/brambow)) ## [v0.85.0](https://github.com/Semantic-Org/Semantic-UI-React/tree/v0.85.0) (2019-02-04) @@ -162,6 +202,7 @@ - docs\(ComponentExample\): allow to disable HTML preview [\#3404](https://github.com/Semantic-Org/Semantic-UI-React/pull/3404) ([layershifter](https://github.com/layershifter)) - docs\(Examples\): add ability to export examples to CodeSandbox [\#3399](https://github.com/Semantic-Org/Semantic-UI-React/pull/3399) ([layershifter](https://github.com/layershifter)) - fix\(docs\): fix a polyfill loading for IE11 [\#3395](https://github.com/Semantic-Org/Semantic-UI-React/pull/3395) ([oolleegg55](https://github.com/oolleegg55)) +- fix\(Icon\): update typings for `corner` prop [\#3393](https://github.com/Semantic-Org/Semantic-UI-React/pull/3393) ([areading314](https://github.com/areading314)) - fix\(Dropdown\): prevent calling onChange unless value changed [\#3391](https://github.com/Semantic-Org/Semantic-UI-React/pull/3391) ([zarend](https://github.com/zarend)) - chore\(package\): upgrade keyboard-key [\#3390](https://github.com/Semantic-Org/Semantic-UI-React/pull/3390) ([levithomason](https://github.com/levithomason)) - chore\(package\): update karma and webpack [\#3383](https://github.com/Semantic-Org/Semantic-UI-React/pull/3383) ([layershifter](https://github.com/layershifter)) @@ -276,21 +317,6 @@ - fix\(Dropdown\): fix deepEqual bug [\#3104](https://github.com/Semantic-Org/Semantic-UI-React/pull/3104) ([pedromtorres](https://github.com/pedromtorres)) - fix\(docs\): fix issues with local builds [\#3098](https://github.com/Semantic-Org/Semantic-UI-React/pull/3098) ([layershifter](https://github.com/layershifter)) -## [v0.82.3](https://github.com/Semantic-Org/Semantic-UI-React/tree/v0.82.3) (2018-08-22) -[Full Changelog](https://github.com/Semantic-Org/Semantic-UI-React/compare/v0.82.2...v0.82.3) - -**Merged pull requests:** - -- fix\(Icon\): update icon names [\#3092](https://github.com/Semantic-Org/Semantic-UI-React/pull/3092) ([levithomason](https://github.com/levithomason)) -- chore\(package\): update Babel to RC1 [\#3086](https://github.com/Semantic-Org/Semantic-UI-React/pull/3086) ([layershifter](https://github.com/layershifter)) -- chore\(build\): fixes for UMD build [\#3085](https://github.com/Semantic-Org/Semantic-UI-React/pull/3085) ([layershifter](https://github.com/layershifter)) -- chore\(package\): bump react-sandbox-render [\#3084](https://github.com/Semantic-Org/Semantic-UI-React/pull/3084) ([layershifter](https://github.com/layershifter)) -- fix\(Message\): export size prop in typings [\#3083](https://github.com/Semantic-Org/Semantic-UI-React/pull/3083) ([layershifter](https://github.com/layershifter)) -- docs\(Item\): cleanup examples [\#3082](https://github.com/Semantic-Org/Semantic-UI-React/pull/3082) ([ChenjieZhou](https://github.com/ChenjieZhou)) -- chore\(config\): remove unused options [\#3080](https://github.com/Semantic-Org/Semantic-UI-React/pull/3080) ([layershifter](https://github.com/layershifter)) -- docs\(build\): fix reloading of examples sources [\#3075](https://github.com/Semantic-Org/Semantic-UI-React/pull/3075) ([layershifter](https://github.com/layershifter)) -- docs\(ComponentExample\): fix display of children [\#3070](https://github.com/Semantic-Org/Semantic-UI-React/pull/3070) ([layershifter](https://github.com/layershifter)) - -\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* diff --git a/README.md b/README.md index 00e5c51fc3..0fb8875407 100644 --- a/README.md +++ b/README.md @@ -29,76 +29,30 @@

->Hey, we're in development. Prior to reaching [v1.0.0][6]: -> ->1. **MINOR** versions represent **breaking changes** ->1. **PATCH** versions represent **fixes _and_ features** ->1. There are **no deprecation warnings** between releases ->1. You should consult the [**CHANGELOG**][18] and related issues/PRs for more information - ## Installation & Usage See the [**Documentation**][2] for an introduction, usage information, and examples. ## Built With - - - - - - +

+ + + +

- Amazon Publishing — the full-service publisher of Amazon — [APub.com](https://amazonpublishing.amazon.com) - Netflix's Edge Developer Experience team's numerous [internal apps](https://github.com/Semantic-Org/Semantic-UI-React/issues/1604) - Netflix's [flamescope][31] - Microsoft's [Teams](https://products.office.com/en-US/microsoft-teams/group-chat-software) prototyping -
- And many more... - -
- ## Example Projects This is a listing of example projects and guides that will help you integrate Semantic UI React into your new or existing projects.
Show projects - - ### [webpack][28] - See our webpack 3 example project [here][28] (includes theming). - - ### [SUIcrux][102] - Advanced universal starter with Semantic-UI-React. React/Redux/Lazy-loading/SSR/PWA. - + ### [semantic-ui-react-todos][100] Semantic UI React implementation of [react-redux Todo List][101].
@@ -107,13 +61,14 @@ This is a listing of example projects and guides that will help you integrate Se
Can I use custom Icons? - Yes. Just use <Icon className='my-icon' /> instead of `<Icon name='my-icon' />`. See https://github.com/Semantic-Org/Semantic-UI-React/issues/931#issuecomment-263643210 for detailed info and examples. + Yes. Just use <Icon className='my-icon' /> instead of <Icon name='my-icon' />. See https://github.com/Semantic-Org/Semantic-UI-React/issues/931#issuecomment-263643210 for detailed info and examples.
How do I setup CSS? - There are several options. Refer to our doc on [CSS Usage][23]. +There are several options. Refer to our doc on [CSS Usage][23]. +
@@ -133,7 +88,7 @@ Here are some helpful links: ### [Voice Your Opinion][19] -Help shape this library by weighing in on our [RFC (request for comments)][19] issues. +Help shape this library by weighing in on our [RFC (request for comments)][19] issues. ### [Contribute][1] @@ -141,11 +96,11 @@ Our [CONTRIBUTING.md][1] is a step-by-step setup and development guide. ### [Good First Issue][21] -Issues labeled [`good first issue`][21] are a great way to ease into development on this project. +Issues labeled [`good first issue`][21] are a great way to ease into development on this project. ### [Missing Components][17] -We're seeking component parity with Semantic UI, plus some addons. There is an issue for every missing component, labeled [`new component`][17]. Just comment on the issue you'd like to take. +We're seeking component parity with Semantic UI, plus some addons. There is an issue for every missing component, labeled [`new component`][17]. Just comment on the issue you'd like to take. ### [Help Wanted Label][4] @@ -193,12 +148,11 @@ Made possible only by [@jlukic][32] authoring [Semantic UI][5]. [25]: http://learnsemantic.com/themes/creating.html [26]: https://github.com/levithomason [27]: https://github.com/layershifter -[28]: https://github.com/Semantic-Org/Semantic-UI-React/tree/master/examples [30]: https://github.com/Semantic-Org/Semantic-UI-Meteor [31]: https://github.com/Netflix/flamescope [32]: https://github.com/jlukic + [100]: https://github.com/wyc/semantic-ui-react-todos [101]: https://github.com/reactjs/redux/tree/master/examples/todos -[102]: https://github.com/Metnew/react-semantic.ui-starter diff --git a/bundle-size/bundle.js b/bundle-size/bundle.js new file mode 100644 index 0000000000..99363024e8 --- /dev/null +++ b/bundle-size/bundle.js @@ -0,0 +1,135 @@ +const c = require('ansi-colors') +const glob = require('glob') +const path = require('path') +const terserVersion = require('terser/package.json').version +const TerserWebpackPlugin = require('terser-webpack-plugin') +const webpack = require('webpack') +const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin +const { argv } = require('yargs') + +const config = require('../config') + +// Ensures that production settings for Babel are used +process.env.NODE_ENV = 'build-es' + +/* eslint-disable no-await-in-loop */ +/* eslint-disable no-console */ +/* eslint-disable no-restricted-syntax */ + +// +// Webpack config +// + +const makeWebpackConfig = (entry) => ({ + devtool: false, + mode: 'production', + name: 'client', + target: 'web', + + entry, + output: { + filename: path.basename(entry), + path: config.paths.base('bundle-size', 'dist'), + }, + + module: { + rules: [ + { + test: /\.(js|ts)$/, + loader: 'babel-loader', + exclude: /node_modules/, + options: { + cacheDirectory: true, + }, + }, + ], + }, + externals: { + react: 'react', + 'react-dom': 'reactDOM', + }, + + ...(argv.debug && { + optimization: { + minimizer: [ + new TerserWebpackPlugin({ + cache: true, + parallel: true, + sourceMap: false, + + terserOptions: { + mangle: false, + output: { + beautify: true, + comments: true, + preserve_annotations: true, + }, + }, + }), + ], + }, + }), + + performance: { + hints: false, + }, + plugins: [ + argv.debug && + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + logLevel: 'warn', + openAnalyzer: false, + reportFilename: `${path.basename(entry, '.js')}.html`, + }), + ].filter(Boolean), + resolve: { + alias: { + 'semantic-ui-react': config.paths.dist('es', 'index.js'), + }, + }, +}) + +function webpackAsync(webpackConfig) { + return new Promise((resolve, reject) => { + const compiler = webpack(webpackConfig) + + compiler.run((err, stats) => { + if (err) { + reject(err) + } + + const info = stats.toJson() + + if (stats.hasErrors()) { + reject(new Error(info.errors.toString())) + } + if (stats.hasWarnings()) { + reject(new Error(info.warnings.toString())) + } + + resolve(info) + }) + }) +} + +// +// +// + +;(async () => { + const fixtures = glob.sync('fixtures/*.size.js', { + cwd: __dirname, + }) + + console.log(c.cyan(`ℹ Using Webpack ${webpack.version} & Terser ${terserVersion}`)) + + console.log(c.cyan('ℹ Running following fixtures:')) + console.log(c.cyan(fixtures.map((fixture) => ` - ${fixture}`).join('\n'))) + + for (const fixture of fixtures) { + const fixturePath = config.paths.base('bundle-size', fixture) + + await webpackAsync(makeWebpackConfig(fixturePath)) + console.log(c.green(`✔ Completed: ${fixture}`)) + } +})() diff --git a/bundle-size/fixtures/Button.size.js b/bundle-size/fixtures/Button.size.js new file mode 100644 index 0000000000..1bee78f116 --- /dev/null +++ b/bundle-size/fixtures/Button.size.js @@ -0,0 +1,9 @@ +import { Button } from 'semantic-ui-react' +import React from 'react' +import ReactDOM from 'react-dom' + +function App() { + return +} + +ReactDOM.render(, document.querySelector('#root')) diff --git a/bundle-size/fixtures/Icon.size.js b/bundle-size/fixtures/Icon.size.js new file mode 100644 index 0000000000..fdc60043c9 --- /dev/null +++ b/bundle-size/fixtures/Icon.size.js @@ -0,0 +1,9 @@ +import { Icon } from 'semantic-ui-react' +import React from 'react' +import ReactDOM from 'react-dom' + +function App() { + return +} + +ReactDOM.render(, document.querySelector('#root')) diff --git a/bundle-size/fixtures/Image.size.js b/bundle-size/fixtures/Image.size.js new file mode 100644 index 0000000000..74fb88ce60 --- /dev/null +++ b/bundle-size/fixtures/Image.size.js @@ -0,0 +1,9 @@ +import { Image } from 'semantic-ui-react' +import React from 'react' +import ReactDOM from 'react-dom' + +function App() { + return +} + +ReactDOM.render(, document.querySelector('#root')) diff --git a/bundle-size/fixtures/Portal.size.js b/bundle-size/fixtures/Portal.size.js new file mode 100644 index 0000000000..1d225e4b40 --- /dev/null +++ b/bundle-size/fixtures/Portal.size.js @@ -0,0 +1,9 @@ +import { Portal } from 'semantic-ui-react' +import React from 'react' +import ReactDOM from 'react-dom' + +function App() { + return A button}>Some content +} + +ReactDOM.render(, document.querySelector('#root')) diff --git a/config.js b/config.js index 320e7b93eb..4bf56aaaf0 100644 --- a/config.js +++ b/config.js @@ -61,7 +61,7 @@ const config = { hash: false, // the hash of the compilation version: false, // webpack version info timings: true, // timing info - assets: true, // assets info + assets: false, // assets info chunks: false, // chunk info colors: true, // with console colors chunkModules: false, // built modules info to chunk info @@ -74,6 +74,7 @@ const config = { modulesSort: '', // (string) sort the modules by that field chunksSort: '', // (string) sort the chunks by that field assetsSort: '', // (string) sort the assets by that field + warningsFilter: [/critical dependency:/i], }, } diff --git a/docs/src/App.js b/docs/src/App.js index 87b9a55902..7a84ff61b5 100644 --- a/docs/src/App.js +++ b/docs/src/App.js @@ -11,7 +11,7 @@ import { docTypes } from './utils' const App = ({ componentMenu, versions }) => (
- + <> {/* * We can't place inside of because it will be remounted on page @@ -33,7 +33,7 @@ const App = ({ componentMenu, versions }) => ( - +
) diff --git a/docs/src/components/CarbonAd/CarbonAd.js b/docs/src/components/CarbonAd/CarbonAd.js index b4cf5fdeed..67783fce68 100644 --- a/docs/src/components/CarbonAd/CarbonAd.js +++ b/docs/src/components/CarbonAd/CarbonAd.js @@ -30,10 +30,6 @@ const waitForLoad = () => { } class CarbonAd extends Component { - static propTypes = { - location: PropTypes.object.isRequired, - } - shouldComponentUpdate(nextProps) { return this.props.location.pathname !== nextProps.location.pathname } @@ -73,4 +69,8 @@ class CarbonAd extends Component { } } +CarbonAd.propTypes = { + location: PropTypes.object.isRequired, +} + export default withRouter(CarbonAd) diff --git a/docs/src/components/CarbonAd/CarbonAdNative.js b/docs/src/components/CarbonAd/CarbonAdNative.js index 2f747554cb..75cacfe963 100644 --- a/docs/src/components/CarbonAd/CarbonAdNative.js +++ b/docs/src/components/CarbonAd/CarbonAdNative.js @@ -9,10 +9,6 @@ const debug = makeDebugger('carbon-ad-native') const MAX_FAILED_ADS = 10 class CarbonAdNative extends PureComponent { - static propTypes = { - inverted: PropTypes.bool, - } - state = {} componentDidMount() { @@ -23,7 +19,8 @@ class CarbonAdNative extends PureComponent { this.getAd() } - componentWillUpdate() { + // eslint-disable-next-line camelcase + UNSAFE_componentWillUpdate() { const shouldGetAd = Date.now() - this.timeOfLastAd > 10000 debug('componentWillUpdate', { mounted: this.mounted, shouldGetAd }) if (shouldGetAd) { @@ -177,4 +174,8 @@ class CarbonAdNative extends PureComponent { } } +CarbonAdNative.propTypes = { + inverted: PropTypes.bool, +} + export default CarbonAdNative diff --git a/docs/src/components/CodeEditor/CodeEditor.js b/docs/src/components/CodeEditor/CodeEditor.js index 40a8e19d48..e0188ce109 100644 --- a/docs/src/components/CodeEditor/CodeEditor.js +++ b/docs/src/components/CodeEditor/CodeEditor.js @@ -97,17 +97,6 @@ class CodeEditor extends React.Component { editorRef = React.createRef() name = `docs-editor-${_.uniqueId()}` - static propTypes = { - active: PropTypes.bool, - showCursor: PropTypes.bool, - value: PropTypes.string.isRequired, - } - - static defaultProps = { - active: true, - showCursor: true, - } - componentDidMount() { this.setCursorVisibility(this.props.showCursor) } @@ -159,4 +148,15 @@ class CodeEditor extends React.Component { } } +CodeEditor.propTypes = { + active: PropTypes.bool, + showCursor: PropTypes.bool, + value: PropTypes.string.isRequired, +} + +CodeEditor.defaultProps = { + active: true, + showCursor: true, +} + export default CodeEditor diff --git a/docs/src/components/CodeSnippet/CodeSnippet.js b/docs/src/components/CodeSnippet/CodeSnippet.js index f62e75a0c7..430356a5b1 100644 --- a/docs/src/components/CodeSnippet/CodeSnippet.js +++ b/docs/src/components/CodeSnippet/CodeSnippet.js @@ -1,12 +1,93 @@ -import { CodeSnippet as StardustCodeSnippet } from '@stardust-ui/docs-components' +import _ from 'lodash' +import * as Prism from 'prismjs/components/prism-core' +import PropTypes from 'prop-types' import React from 'react' -import NoSSR from '../NoSSR' +// Order of PrismJS imports there is sensitive +import 'prismjs/components/prism-clike' +import 'prismjs/components/prism-json' +import 'prismjs/components/prism-markup' +import 'prismjs/components/prism-bash' +import 'prismjs/components/prism-javascript' +import 'prismjs/components/prism-jsx' -const CodeSnippet = (props) => ( - - - -) +import CodeSnippetLabel from './CodeSnippetLabel' + +const normalizeToString = (value) => { + if (Array.isArray(value)) { + return value.join('\n') + } + + return _.isObject(value) ? JSON.stringify(value, null, 2) : value +} + +const formatters = { + bash: (val = '') => val.replace(/^[\w]/gm, '$$ $&'), + json: (val) => val, + js: (val = '') => val, + jsx: (val = '') => val, + html: (val = '') => val, +} + +export const formatCode = (code, mode) => { + if (!code) return '' + const formatter = formatters[mode] + + return ( + formatter(normalizeToString(code)) + // remove eof line break, they are not helpful for snippets + .replace(/\n$/, '') + ) +} + +const CodeSnippet = React.memo((props) => { + const { + className, + copyable = true, + fitted, + formattable = true, + label, + mode = 'jsx', + value, + } = props + + const codeClassName = `language-${mode}` + const code = formattable ? formatCode(value, mode) : value + const codeRef = React.useRef(null) + + React.useLayoutEffect(() => { + Prism.highlightElement(codeRef.current) + }) + + return ( +
+ + +
+        
+          {code}
+        
+      
+
+ ) +}) + +CodeSnippet.propTypes = { + className: PropTypes.string, + copyable: PropTypes.bool, + fitted: PropTypes.bool, + formattable: PropTypes.bool, + label: PropTypes.oneOfType([PropTypes.element, PropTypes.bool]), + mode: PropTypes.oneOf(['bash', 'json', 'js', 'jsx', 'html']), + style: PropTypes.object, + value: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), +} export default CodeSnippet diff --git a/docs/src/components/CodeSnippet/CodeSnippetLabel.js b/docs/src/components/CodeSnippet/CodeSnippetLabel.js new file mode 100644 index 0000000000..fc070ea351 --- /dev/null +++ b/docs/src/components/CodeSnippet/CodeSnippetLabel.js @@ -0,0 +1,61 @@ +import PropTypes from 'prop-types' +import * as React from 'react' + +import { useCopyToClipboard } from '../CopyToClipboard' + +const checkIcon = ( + + + +) + +const copyIcon = ( + + + +) + +const CodeSnippetLabel = (props) => { + const { copyable, label, mode, value } = props + const hasLabel = label !== false + + const [active, onCopy] = useCopyToClipboard(value) + + return ( + hasLabel && ( +
+
{label || mode}
+ {copyable &&
{active ? checkIcon : copyIcon}
} +
+ ) + ) +} + +CodeSnippetLabel.propTypes = { + copyable: PropTypes.bool, + label: PropTypes.oneOfType([PropTypes.element, PropTypes.bool]), + mode: PropTypes.oneOf(['bash', 'json', 'js', 'jsx', 'html']), + value: PropTypes.string, +} + +export default CodeSnippetLabel diff --git a/docs/src/components/CodeSnippet/index.js b/docs/src/components/CodeSnippet/index.js index 5116355cf9..e558a054b3 100644 --- a/docs/src/components/CodeSnippet/index.js +++ b/docs/src/components/CodeSnippet/index.js @@ -1 +1,12 @@ -export default from './CodeSnippet' +import React from 'react' +import DefaultCodeSnippet from './CodeSnippet' + +import NoSSR from '../NoSSR' + +const CodeSnippet = (props) => ( + + + +) + +export default CodeSnippet diff --git a/docs/src/components/ComponentDoc/ComponentControls/ComponentControlsCodeSandbox.js b/docs/src/components/ComponentDoc/ComponentControls/ComponentControlsCodeSandbox.js index 16599ba260..ec9cdf7938 100644 --- a/docs/src/components/ComponentDoc/ComponentControls/ComponentControlsCodeSandbox.js +++ b/docs/src/components/ComponentDoc/ComponentControls/ComponentControlsCodeSandbox.js @@ -10,11 +10,12 @@ const appTemplate = `import React from "react"; import ReactDOM from "react-dom"; import { Container, Header, List } from "semantic-ui-react"; +import pkg from 'semantic-ui-react/package.json' import Example from "./example"; const App = ({ children }) => ( -
This example is powered by Semantic UI React 😊
+
This example is powered by Semantic UI React {pkg.version} 😊
+ + + + + ) +} +class ComponentControlsCodeSandbox extends React.Component { state = { exampleCode: '', sandboxUrl: '', @@ -96,7 +108,7 @@ class ComponentControlsCodeSandbox extends React.Component { example={enhanceExampleCode(exampleCode)} providedFiles={{ 'index.js': { content: appTemplate }, - 'package.json': createPackageJson(), + 'package.json': createPackageJson(exampleCode), }} skipRedirect template='create-react-app' @@ -108,10 +120,7 @@ class ComponentControlsCodeSandbox extends React.Component { } title='Export to CodeSandbox' /> ) @@ -123,4 +132,9 @@ class ComponentControlsCodeSandbox extends React.Component { } } +ComponentControlsCodeSandbox.propTypes = { + exampleCode: PropTypes.string.isRequired, + visible: PropTypes.bool.isRequired, +} + export default ComponentControlsCodeSandbox diff --git a/docs/src/components/ComponentDoc/ComponentControls/ComponentControlsCopyLink.js b/docs/src/components/ComponentDoc/ComponentControls/ComponentControlsCopyLink.js index 643ce887f5..4a196661d2 100644 --- a/docs/src/components/ComponentDoc/ComponentControls/ComponentControlsCopyLink.js +++ b/docs/src/components/ComponentDoc/ComponentControls/ComponentControlsCopyLink.js @@ -5,11 +5,6 @@ import { Icon, Menu } from 'semantic-ui-react' export default class ComponentControlsCopyLink extends Component { state = {} - static propTypes = { - anchorName: PropTypes.string, - onClick: PropTypes.func, - } - shouldComponentUpdate(nextProps, nextState) { return this.state.active !== nextState.active } @@ -40,3 +35,8 @@ export default class ComponentControlsCopyLink extends Component { ) } } + +ComponentControlsCopyLink.propTypes = { + anchorName: PropTypes.string, + onClick: PropTypes.func, +} diff --git a/docs/src/components/ComponentDoc/ComponentControls/createPackageJson.js b/docs/src/components/ComponentDoc/ComponentControls/createPackageJson.js index 0d70aa806d..e388520575 100644 --- a/docs/src/components/ComponentDoc/ComponentControls/createPackageJson.js +++ b/docs/src/components/ComponentDoc/ComponentControls/createPackageJson.js @@ -3,20 +3,31 @@ import { externals } from 'docs/src/components/ComponentDoc/ExampleEditor/render const name = 'semantic-ui-example' const description = 'An exported example from Semantic UI React, https://react.semantic-ui.com/' -const dependencies = { - ..._.mapValues(externals, () => 'latest'), - // required to enable all features due old templates in https://github.com/codesandbox/codesandbox-importers - 'react-scripts': 'latest', + +function createDependencies(code) { + // Will include only required packages intentionally like "react" or required by a current example + const filteredPackages = _.pickBy( + externals, + (declaration, importName) => + declaration.required || new RegExp(`from ['|"]${importName}['|"]`).exec(code), + ) + + return { + ..._.mapValues(filteredPackages, (pkg) => pkg.version), + // required to enable all features due old templates in https://github.com/codesandbox/codesandbox-importers + // https://github.com/microsoft/fluent-ui-react/issues/1519 + 'react-scripts': 'latest', + } } -const createPackageJson = () => ({ +const createPackageJson = (code) => ({ content: JSON.stringify( { name, version: '1.0.0', description, main: 'index.js', - dependencies, + dependencies: createDependencies(code), }, null, 2, diff --git a/docs/src/components/ComponentDoc/ComponentControls/enhanceExampleCode.js b/docs/src/components/ComponentDoc/ComponentControls/enhanceExampleCode.js index b20968e01c..93d19e6848 100644 --- a/docs/src/components/ComponentDoc/ComponentControls/enhanceExampleCode.js +++ b/docs/src/components/ComponentDoc/ComponentControls/enhanceExampleCode.js @@ -1,8 +1,8 @@ -const imagesRegex = /\/images\//gm +const imagesRegex = /'\/images\//gm const enhanceExampleCode = (code) => { // To have absolute paths on CodeSandbox for images - return code.replace(imagesRegex, 'https://react.semantic-ui.com/images/') + return code.replace(imagesRegex, "'https://react.semantic-ui.com/images/") } export default enhanceExampleCode diff --git a/docs/src/components/ComponentDoc/ComponentDoc.js b/docs/src/components/ComponentDoc/ComponentDoc.js index f126ffa4f6..34bad666db 100644 --- a/docs/src/components/ComponentDoc/ComponentDoc.js +++ b/docs/src/components/ComponentDoc/ComponentDoc.js @@ -2,7 +2,7 @@ import _ from 'lodash' import PropTypes from 'prop-types' import React, { Component, createRef } from 'react' import { withRouter, withRouteData } from 'react-static' -import { Grid, Header, Icon } from 'semantic-ui-react' +import { Grid, Header, Icon, Label, Popup } from 'semantic-ui-react' import DocsLayout from 'docs/src/components/DocsLayout' import { docTypes, examplePathToHash } from 'docs/src/utils' @@ -20,16 +20,6 @@ const exampleEndStyle = { } class ComponentDoc extends Component { - static propTypes = { - componentsInfo: PropTypes.objectOf(docTypes.componentInfoShape).isRequired, - displayName: PropTypes.string.isRequired, - history: PropTypes.object.isRequired, - location: PropTypes.object.isRequired, - seeTags: docTypes.seeTags.isRequired, - sidebarSections: docTypes.sidebarSections.isRequired, - title: PropTypes.string.isRequired, - } - state = {} examplesRef = createRef() @@ -57,7 +47,7 @@ class ComponentDoc extends Component { } render() { - const { componentsInfo, displayName, seeTags, sidebarSections } = this.props + const { componentsInfo, displayName, deprecated, seeTags, sidebarSections } = this.props const activePath = _.findKey(this.state.exampleStates) const componentInfo = componentsInfo[displayName] const contextValue = { ...this.props, onVisibilityChange: this.handleExampleVisibility } @@ -70,7 +60,16 @@ class ComponentDoc extends Component {
+ {displayName} + {deprecated && ( + Deprecated}> + This component is deprecated and will be removed in the next major release. + + )} + + } subheader={_.join(componentInfo.docblock.description, ' ')} /> @@ -114,4 +113,15 @@ class ComponentDoc extends Component { } } +ComponentDoc.propTypes = { + componentsInfo: PropTypes.objectOf(docTypes.componentInfoShape).isRequired, + displayName: PropTypes.string.isRequired, + deprecated: PropTypes.bool.isRequired, + history: PropTypes.object.isRequired, + location: PropTypes.object.isRequired, + seeTags: docTypes.seeTags.isRequired, + sidebarSections: docTypes.sidebarSections.isRequired, + title: PropTypes.string.isRequired, +} + export default withRouteData(withRouter(ComponentDoc)) diff --git a/docs/src/components/ComponentDoc/ComponentDocLinks.js b/docs/src/components/ComponentDoc/ComponentDocLinks.js index 589ea6743c..7e08fe6034 100644 --- a/docs/src/components/ComponentDoc/ComponentDocLinks.js +++ b/docs/src/components/ComponentDoc/ComponentDocLinks.js @@ -15,13 +15,6 @@ const linkListStyle = { } export default class ComponentDocLinks extends PureComponent { - static propTypes = { - displayName: PropTypes.string.isRequired, - parentDisplayName: PropTypes.string, - repoPath: PropTypes.string.isRequired, - type: PropTypes.string.isRequired, - } - render() { const { displayName, parentDisplayName, repoPath, type } = this.props const ghLink = `${repoURL}/blob/master/${repoPath}` @@ -54,3 +47,10 @@ export default class ComponentDocLinks extends PureComponent { ) } } + +ComponentDocLinks.propTypes = { + displayName: PropTypes.string.isRequired, + parentDisplayName: PropTypes.string, + repoPath: PropTypes.string.isRequired, + type: PropTypes.string.isRequired, +} diff --git a/docs/src/components/ComponentDoc/ComponentExample/ComponentExample.js b/docs/src/components/ComponentDoc/ComponentExample/ComponentExample.js index d36ea1b113..f4c65a686d 100644 --- a/docs/src/components/ComponentDoc/ComponentExample/ComponentExample.js +++ b/docs/src/components/ComponentDoc/ComponentExample/ComponentExample.js @@ -1,10 +1,9 @@ -import { KnobProvider, LogInspector, CodeSnippet } from '@stardust-ui/docs-components' import cx from 'classnames' import copyToClipboard from 'copy-to-clipboard' import PropTypes from 'prop-types' import React, { Component } from 'react' -import VisibilitySensor from 'react-visibility-sensor' -import { Button, Checkbox, Grid, Label } from 'semantic-ui-react' +import { InView } from 'react-intersection-observer' +import { Grid } from 'semantic-ui-react' import { examplePathToHash, scrollToAnchor } from 'docs/src/utils' import CarbonAdNative from 'docs/src/components/CarbonAd/CarbonAdNative' @@ -12,7 +11,6 @@ import formatCode from 'docs/src/utils/formatCode' import ComponentControls from '../ComponentControls' import ExampleEditor from '../ExampleEditor' import ComponentDocContext from '../ComponentDocContext' -import ComponentExampleKnobs from './ComponentExampleKnobs' import ComponentExampleTitle from './ComponentExampleTitle' const childrenStyle = { @@ -25,68 +23,11 @@ const componentControlsStyle = { width: 'auto', } -/* eslint-disable react/prop-types */ -const knobComponents = { - KnobControl: (props) => ( -
- {props.children} -
- ), - KnobBoolean: (props) => ( - props.setValue(data.checked)} - type='checkbox' - value={props.value} - /> - ), - KnobLabel: (props) => ( - - ), - LogInspector: (props) => ( - <> - - Event log - - - - - - - - - - ), -} - -/* eslint-enable react/prop-types */ - /** * Renders a `component` and the raw `code` that produced it. - * Allows toggling the the raw `code` code block. + * Allows toggling the raw `code` code block. */ class ComponentExample extends Component { - static propTypes = { - children: PropTypes.node, - description: PropTypes.node, - examplePath: PropTypes.string.isRequired, - history: PropTypes.object.isRequired, - location: PropTypes.object.isRequired, - onVisibilityChange: PropTypes.func.isRequired, - renderHtml: PropTypes.bool, - sourceCode: PropTypes.string.isRequired, - suiVersion: PropTypes.string, - title: PropTypes.node, - } - - static defaultProps = { - renderHtml: true, - } - constructor(props) { super(props) @@ -185,11 +126,7 @@ class ComponentExample extends Component { } = this.state return ( - +
@@ -213,40 +150,53 @@ class ComponentExample extends Component { /> - - - {children && ( - - {children} - - )} - - - - + {children && ( + + {children} - + )} + + + + {isActiveHash && }
-
+ ) } } +ComponentExample.propTypes = { + children: PropTypes.node, + description: PropTypes.node, + examplePath: PropTypes.string.isRequired, + history: PropTypes.object.isRequired, + location: PropTypes.object.isRequired, + onVisibilityChange: PropTypes.func.isRequired, + renderHtml: PropTypes.bool, + sourceCode: PropTypes.string.isRequired, + suiVersion: PropTypes.string, + title: PropTypes.node, +} + +ComponentExample.defaultProps = { + renderHtml: true, +} + /* TODO: Replace this temporary component with hooks */ const Wrapper = (props) => { const { exampleSources, ...rest } = React.useContext(ComponentDocContext) diff --git a/docs/src/components/ComponentDoc/ComponentExample/ComponentExampleKnobs.js b/docs/src/components/ComponentDoc/ComponentExample/ComponentExampleKnobs.js deleted file mode 100644 index 6e1470f595..0000000000 --- a/docs/src/components/ComponentDoc/ComponentExample/ComponentExampleKnobs.js +++ /dev/null @@ -1,43 +0,0 @@ -import { CodeSnippet, KnobInspector, useKnobValues } from '@stardust-ui/docs-components' -import _ from 'lodash' -import React from 'react' -import { Grid } from 'semantic-ui-react' - -const columnStyles = { - padding: 0, -} - -const knobsStyles = { - background: 'whitesmoke', - color: '#777', - lineHeight: '1.5', - padding: '1rem', -} - -const rowStyles = { - padding: 0, -} - -const ComponentExampleKnobs = () => { - const knobValues = useKnobValues() - const values = _.fromPairs(knobValues.map((knob) => [knob.name, knob.value])) - - return ( - - {(knobs) => - knobs && ( - - -
{knobs}
-
- - - -
- ) - } -
- ) -} - -export default ComponentExampleKnobs diff --git a/docs/src/components/ComponentDoc/ComponentExample/ComponentExampleTitle.js b/docs/src/components/ComponentDoc/ComponentExample/ComponentExampleTitle.js index 836c4af00a..d874981278 100644 --- a/docs/src/components/ComponentDoc/ComponentExample/ComponentExampleTitle.js +++ b/docs/src/components/ComponentDoc/ComponentExample/ComponentExampleTitle.js @@ -7,12 +7,6 @@ const titleStyle = { } export default class ComponentExampleTitle extends Component { - static propTypes = { - description: PropTypes.node, - title: PropTypes.node, - suiVersion: PropTypes.string, - } - shouldComponentUpdate() { return false } @@ -40,3 +34,9 @@ export default class ComponentExampleTitle extends Component { ) } } + +ComponentExampleTitle.propTypes = { + description: PropTypes.node, + title: PropTypes.node, + suiVersion: PropTypes.string, +} diff --git a/docs/src/components/ComponentDoc/ComponentExamples.js b/docs/src/components/ComponentDoc/ComponentExamples.js index 8a91995080..a61f71493a 100644 --- a/docs/src/components/ComponentDoc/ComponentExamples.js +++ b/docs/src/components/ComponentDoc/ComponentExamples.js @@ -5,12 +5,6 @@ import { Grid } from 'semantic-ui-react' import ContributionPrompt from './ContributionPrompt' export default class ComponentExamples extends Component { - static propTypes = { - displayName: PropTypes.string.isRequired, - examplesExist: PropTypes.bool.isRequired, - type: PropTypes.string.isRequired, - } - renderExamples = () => { const { displayName, type } = this.props @@ -36,3 +30,9 @@ export default class ComponentExamples extends Component { return examplesExist ? this.renderExamples() : this.renderMissingExamples() } } + +ComponentExamples.propTypes = { + displayName: PropTypes.string.isRequired, + examplesExist: PropTypes.bool.isRequired, + type: PropTypes.string.isRequired, +} diff --git a/docs/src/components/ComponentDoc/ComponentProp/ComponentPropDefaultValue.js b/docs/src/components/ComponentDoc/ComponentProp/ComponentPropDefaultValue.js index fa64be516c..06752fb812 100644 --- a/docs/src/components/ComponentDoc/ComponentProp/ComponentPropDefaultValue.js +++ b/docs/src/components/ComponentDoc/ComponentProp/ComponentPropDefaultValue.js @@ -3,12 +3,12 @@ import PropTypes from 'prop-types' import React, { PureComponent } from 'react' export default class ComponentPropDefaultValue extends PureComponent { - static propTypes = { - value: PropTypes.node, - } - render() { const { value } = this.props return _.isNil(value) ? null : {value} } } + +ComponentPropDefaultValue.propTypes = { + value: PropTypes.node, +} diff --git a/docs/src/components/ComponentDoc/ComponentProp/ComponentPropDescription.js b/docs/src/components/ComponentDoc/ComponentProp/ComponentPropDescription.js index 3c62eab401..8a6eea1306 100644 --- a/docs/src/components/ComponentDoc/ComponentProp/ComponentPropDescription.js +++ b/docs/src/components/ComponentDoc/ComponentProp/ComponentPropDescription.js @@ -3,12 +3,12 @@ import PropTypes from 'prop-types' import React, { PureComponent } from 'react' export default class ComponentPropDescription extends PureComponent { - static propTypes = { - description: PropTypes.arrayOf(PropTypes.string), - } - render() { const { description } = this.props return

{_.map(description, (line) => [line,
])}

} } + +ComponentPropDescription.propTypes = { + description: PropTypes.arrayOf(PropTypes.string), +} diff --git a/docs/src/components/ComponentDoc/ComponentProp/ComponentPropName.js b/docs/src/components/ComponentDoc/ComponentProp/ComponentPropName.js index 418c09c7b6..e49e8ab40d 100644 --- a/docs/src/components/ComponentDoc/ComponentProp/ComponentPropName.js +++ b/docs/src/components/ComponentDoc/ComponentProp/ComponentPropName.js @@ -3,11 +3,6 @@ import React, { PureComponent } from 'react' import { Icon, Popup } from 'semantic-ui-react' export default class ComponentPropName extends PureComponent { - static propTypes = { - name: PropTypes.string, - required: PropTypes.bool, - } - render() { const { name, required } = this.props @@ -27,3 +22,8 @@ export default class ComponentPropName extends PureComponent { ) } } + +ComponentPropName.propTypes = { + name: PropTypes.string, + required: PropTypes.bool, +} diff --git a/docs/src/components/ComponentDoc/ComponentProps/ComponentProps.js b/docs/src/components/ComponentDoc/ComponentProps/ComponentProps.js index bb6c4ef8ce..ee01160df8 100644 --- a/docs/src/components/ComponentDoc/ComponentProps/ComponentProps.js +++ b/docs/src/components/ComponentDoc/ComponentProps/ComponentProps.js @@ -11,11 +11,6 @@ import ComponentPropsDescription from './ComponentPropsDescription' const propsContainerStyle = { overflowX: 'auto' } export default class ComponentProps extends Component { - static propTypes = { - componentsInfo: PropTypes.objectOf(docTypes.componentInfoShape).isRequired, - displayName: PropTypes.string.isRequired, - } - state = {} static getDerivedStateFromProps(props, state) { @@ -45,7 +40,7 @@ export default class ComponentProps extends Component { const description = _.get(docblock, 'description', []) return ( - + <> )} - + ) } } + +ComponentProps.propTypes = { + componentsInfo: PropTypes.objectOf(docTypes.componentInfoShape).isRequired, + displayName: PropTypes.string.isRequired, +} diff --git a/docs/src/components/ComponentDoc/ComponentSidebar/ComponentSidebarSection.js b/docs/src/components/ComponentDoc/ComponentSidebar/ComponentSidebarSection.js index 9278cf82b0..6a9a70bab4 100644 --- a/docs/src/components/ComponentDoc/ComponentSidebar/ComponentSidebarSection.js +++ b/docs/src/components/ComponentDoc/ComponentSidebar/ComponentSidebarSection.js @@ -4,19 +4,6 @@ import React, { PureComponent } from 'react' import { Accordion, Icon, Menu } from 'semantic-ui-react' export default class ComponentSidebarSection extends PureComponent { - static propTypes = { - activePath: PropTypes.string, - examples: PropTypes.arrayOf( - PropTypes.shape({ - title: PropTypes.string, - examplePath: PropTypes.string, - }), - ), - sectionName: PropTypes.string, - onItemClick: PropTypes.func, - onTitleClick: PropTypes.func, - } - state = {} static getDerivedStateFromProps(props, state) { @@ -66,3 +53,16 @@ export default class ComponentSidebarSection extends PureComponent { ) } } + +ComponentSidebarSection.propTypes = { + activePath: PropTypes.string, + examples: PropTypes.arrayOf( + PropTypes.shape({ + title: PropTypes.string, + examplePath: PropTypes.string, + }), + ), + sectionName: PropTypes.string, + onItemClick: PropTypes.func, + onTitleClick: PropTypes.func, +} diff --git a/docs/src/components/ComponentDoc/ComponentTable/ComponentTableRow.js b/docs/src/components/ComponentDoc/ComponentTable/ComponentTableRow.js index d6391f43b4..ba1322b582 100644 --- a/docs/src/components/ComponentDoc/ComponentTable/ComponentTableRow.js +++ b/docs/src/components/ComponentDoc/ComponentTable/ComponentTableRow.js @@ -9,16 +9,6 @@ import ComponentPropFunctionSignature from '../ComponentProp/ComponentPropFuncti import ComponentPropName from '../ComponentProp/ComponentPropName' export default class ComponentTableRow extends Component { - static propTypes = { - defaultValue: PropTypes.string, - description: PropTypes.arrayOf(PropTypes.string), - name: PropTypes.string, - required: PropTypes.bool, - tags: PropTypes.array, - type: PropTypes.string, - value: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), - } - state = {} toggleEnums = () => this.setState((prevState) => ({ showEnums: !prevState.showEnums })) @@ -50,3 +40,13 @@ export default class ComponentTableRow extends Component { ) } } + +ComponentTableRow.propTypes = { + defaultValue: PropTypes.string, + description: PropTypes.arrayOf(PropTypes.string), + name: PropTypes.string, + required: PropTypes.bool, + tags: PropTypes.array, + type: PropTypes.string, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), +} diff --git a/docs/src/components/ComponentDoc/ExampleEditor/ExampleEditor.js b/docs/src/components/ComponentDoc/ExampleEditor/ExampleEditor.js index 66a491fa39..f545e6b82d 100644 --- a/docs/src/components/ComponentDoc/ExampleEditor/ExampleEditor.js +++ b/docs/src/components/ComponentDoc/ExampleEditor/ExampleEditor.js @@ -50,7 +50,7 @@ const ExampleEditor = (props) => { unstable_hot > {({ element, error, markup }) => ( - + <> { )} - + )} ) diff --git a/docs/src/components/ComponentDoc/ExampleEditor/ExampleEditorMenu.js b/docs/src/components/ComponentDoc/ExampleEditor/ExampleEditorMenu.js index dfbd0bad27..9a5bbde753 100644 --- a/docs/src/components/ComponentDoc/ExampleEditor/ExampleEditorMenu.js +++ b/docs/src/components/ComponentDoc/ExampleEditor/ExampleEditorMenu.js @@ -30,15 +30,6 @@ const getGithubEditHref = (examplePath) => { class ExampleEditorMenu extends PureComponent { state = {} - static propTypes = { - examplePath: PropTypes.string.isRequired, - hasError: PropTypes.bool.isRequired, - hasCodeChanged: PropTypes.bool.isRequired, - onCodeFormat: PropTypes.func.isRequired, - onCodeReset: PropTypes.func.isRequired, - sourceCode: PropTypes.string.isRequired, - } - constructor(props) { super(props) this.state = { @@ -98,17 +89,15 @@ class ExampleEditorMenu extends PureComponent {