From 62b2d587c9c885fd1d76abdb5ff5c4d6e835e49e Mon Sep 17 00:00:00 2001 From: Rogin Farrer Date: Sun, 3 Oct 2021 17:04:45 -0400 Subject: [PATCH] refactor: Repo dependency overhaul (#73) * minor: Repo dependency overhaul * remove old github actions file * add nvmrc * add files to package.json --- .github/workflows/release.yml | 45 + .github/workflows/test.yml | 33 - .nvmrc | 1 + .storybook/config.js | 1 - .storybook/main.js | 43 +- .storybook/preview-body.html | 3 - .storybook/preview.js | 9 + CHANGELOG.md | 26 +- MIGRATION-2.x-to-3.x.md | 11 +- README.md | 50 +- cypress.json | 3 - cypress/.eslintrc.json | 6 - cypress/fixtures/example.json | 5 - cypress/integration/example-spec.js | 49 - cypress/integration/examples/actions.spec.js | 298 - cypress/integration/examples/aliasing.spec.js | 42 - .../integration/examples/assertions.spec.js | 168 - .../integration/examples/connectors.spec.js | 97 - cypress/integration/examples/cookies.spec.js | 78 - .../integration/examples/cypress_api.spec.js | 222 - cypress/integration/examples/files.spec.js | 114 - .../examples/local_storage.spec.js | 52 - cypress/integration/examples/location.spec.js | 32 - cypress/integration/examples/misc.spec.js | 92 - .../integration/examples/navigation.spec.js | 56 - .../examples/network_requests.spec.js | 195 - cypress/integration/examples/querying.spec.js | 114 - .../examples/spies_stubs_clocks.spec.js | 95 - .../integration/examples/traversal.spec.js | 121 - .../integration/examples/utilities.spec.js | 133 - cypress/integration/examples/viewport.spec.js | 59 - cypress/integration/examples/waiting.spec.js | 34 - cypress/integration/examples/window.spec.js | 22 - cypress/plugins/index.js | 21 - cypress/support/commands.js | 25 - cypress/support/index.js | 20 - example/index.tsx | 22 +- package.json | 121 +- setupTests.ts | 1 + src/__tests__/index.test.tsx | 176 +- src/__tests__/mocks/{utils.js => utils.ts} | 6 +- src/__tests__/setupTests.ts | 1 - src/__tests__/utils.test.tsx | 154 +- src/global.d.ts | 2 +- src/index.ts | 96 +- {stories => src/stories}/basic.stories.tsx | 24 +- {stories => src/stories}/components.tsx | 20 +- {stories => src/stories}/div.stories.tsx | 16 +- {stories => src/stories}/nested.stories.tsx | 22 +- {stories => src/stories}/unmount.stories.tsx | 27 +- src/types.ts | 80 +- src/utils.ts | 110 +- tsconfig.json | 4 +- yarn.lock | 14521 ++++++++-------- 54 files changed, 8115 insertions(+), 9663 deletions(-) create mode 100644 .github/workflows/release.yml delete mode 100644 .github/workflows/test.yml create mode 100644 .nvmrc delete mode 100644 .storybook/config.js delete mode 100644 .storybook/preview-body.html create mode 100644 .storybook/preview.js delete mode 100644 cypress.json delete mode 100644 cypress/.eslintrc.json delete mode 100644 cypress/fixtures/example.json delete mode 100644 cypress/integration/example-spec.js delete mode 100644 cypress/integration/examples/actions.spec.js delete mode 100644 cypress/integration/examples/aliasing.spec.js delete mode 100644 cypress/integration/examples/assertions.spec.js delete mode 100644 cypress/integration/examples/connectors.spec.js delete mode 100644 cypress/integration/examples/cookies.spec.js delete mode 100644 cypress/integration/examples/cypress_api.spec.js delete mode 100644 cypress/integration/examples/files.spec.js delete mode 100644 cypress/integration/examples/local_storage.spec.js delete mode 100644 cypress/integration/examples/location.spec.js delete mode 100644 cypress/integration/examples/misc.spec.js delete mode 100644 cypress/integration/examples/navigation.spec.js delete mode 100644 cypress/integration/examples/network_requests.spec.js delete mode 100644 cypress/integration/examples/querying.spec.js delete mode 100644 cypress/integration/examples/spies_stubs_clocks.spec.js delete mode 100644 cypress/integration/examples/traversal.spec.js delete mode 100644 cypress/integration/examples/utilities.spec.js delete mode 100644 cypress/integration/examples/viewport.spec.js delete mode 100644 cypress/integration/examples/waiting.spec.js delete mode 100644 cypress/integration/examples/window.spec.js delete mode 100644 cypress/plugins/index.js delete mode 100644 cypress/support/commands.js delete mode 100644 cypress/support/index.js create mode 100644 setupTests.ts rename src/__tests__/mocks/{utils.js => utils.ts} (72%) delete mode 100644 src/__tests__/setupTests.ts rename {stories => src/stories}/basic.stories.tsx (70%) rename {stories => src/stories}/components.tsx (92%) rename {stories => src/stories}/div.stories.tsx (63%) rename {stories => src/stories}/nested.stories.tsx (88%) rename {stories => src/stories}/unmount.stories.tsx (63%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a29c8b6 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,45 @@ +name: Release npm package + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + name: 'CI' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 14 + - name: Install Dependencies + uses: bahmutov/npm-install@v1 + - name: Build + run: yarn build + - name: Lint + run: yarn lint + - name: Test + run: yarn test + + release: + name: Publish to NPM + needs: test + # publish only when merged in master on original repo, not on PR + if: github.repository == 'roginfarrer/react-collapsed' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: 14 + - name: Install Dependencies + uses: bahmutov/npm-install@v1 + - name: Build + run: yarn build + - run: npx semantic-release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 8309bf5..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: CI -on: [push] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Cache node modules - uses: actions/cache@v1 - env: - cache-name: cache-node-modules - with: - path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-build- - ${{ runner.os }}- - - - name: Install Dependencies - run: yarn install - - - name: Build - run: yarn build - - - name: Test - run: yarn test - - - name: Lint - run: yarn lint diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..c2324e8 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +14.18.0 diff --git a/.storybook/config.js b/.storybook/config.js deleted file mode 100644 index 8fca887..0000000 --- a/.storybook/config.js +++ /dev/null @@ -1 +0,0 @@ -import 'cypress-storybook/react'; diff --git a/.storybook/main.js b/.storybook/main.js index dd2650c..5e7f178 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,36 +1,11 @@ -const webpack = require('webpack'); - module.exports = { - stories: ['../stories/**/*.stories.(ts|tsx)'], - addons: [ - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addon-a11y', - '@storybook/addon-storysource', + "stories": [ + "../src/**/*.stories.mdx", + "../src/**/*.stories.@(js|jsx|ts|tsx)" ], - webpackFinal: async config => { - config.module.rules.push({ - test: /\.(ts|tsx)$/, - use: [ - { - loader: require.resolve('ts-loader'), - options: { - transpileOnly: true, - }, - }, - { - loader: require.resolve('react-docgen-typescript-loader'), - }, - ], - }); - - config.resolve.extensions.push('.ts', '.tsx'); - config.plugins.push( - new webpack.DefinePlugin({ - __DEV__: JSON.stringify(process.env.NODE_ENV), - }) - ); - - return config; - }, -}; + "addons": [ + "@storybook/addon-links", + "@storybook/addon-essentials", + "@storybook/addon-a11y" + ] +} diff --git a/.storybook/preview-body.html b/.storybook/preview-body.html deleted file mode 100644 index 3e377e7..0000000 --- a/.storybook/preview-body.html +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/.storybook/preview.js b/.storybook/preview.js new file mode 100644 index 0000000..48afd56 --- /dev/null +++ b/.storybook/preview.js @@ -0,0 +1,9 @@ +export const parameters = { + actions: { argTypesRegex: "^on[A-Z].*" }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a7cfb2..2353f5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,23 +2,23 @@ Complete rewrite using React hooks! -* Ends support for React versions < 16.8.x -* Library now exports a custom hook in lieu of a render prop component -* Adds support for unmounting the contents of the Collapse element when closed +- Ends support for React versions < 16.8.x +- Library now exports a custom hook in lieu of a render prop component +- Adds support for unmounting the contents of the Collapse element when closed ```js -import React from 'react'; -import useCollapse from 'react-collapsed'; +import React from 'react' +import useCollapse from 'react-collapsed' function Demo() { - const {getCollapseProps, getToggleProps, isOpen} = useCollapse(); + const { getCollapseProps, getToggleProps, isOpen } = useCollapse() return ( <>
Collapsed content πŸ™ˆ
- ); + ) } ``` @@ -26,20 +26,20 @@ function Demo() { Bumped to full release! :) -* `duration`, `easing`, and `delay` now support taking an object with `in` and `out` keys to configure differing in-and-out transitions +- `duration`, `easing`, and `delay` now support taking an object with `in` and `out` keys to configure differing in-and-out transitions # 0.2.0 ### Breaking Changes -* `getCollapsibleProps` => `getCollapseProps`. Renamed since it's easier to spell πŸ˜… +- `getCollapsibleProps` => `getCollapseProps`. Renamed since it's easier to spell πŸ˜… ### Other -* Slew of Flow bug fixes -* Improved documentation +- Slew of Flow bug fixes +- Improved documentation # 0.1.3 -* ESLINT wasn't working properly - fixed this -* Added `files` key to package.json to improve NPM load +- ESLINT wasn't working properly - fixed this +- Added `files` key to package.json to improve NPM load diff --git a/MIGRATION-2.x-to-3.x.md b/MIGRATION-2.x-to-3.x.md index 12ba319..e0d1a3d 100644 --- a/MIGRATION-2.x-to-3.x.md +++ b/MIGRATION-2.x-to-3.x.md @@ -76,15 +76,15 @@ Now, you must provide a boolean or a function that returns a boolean: ```javascript function Collapse() { - const [mountChildren, setMountChildren] = useState(false); + const [mountChildren, setMountChildren] = useState(false) const { getToggleProps, getCollapseProps } = useCollapse({ onCollapseEnd() { - setMountChildren(false); + setMountChildren(false) }, onExpandStart() { - setMountChildren(true); + setMountChildren(true) }, - }); + }) return (
@@ -93,7 +93,6 @@ function Collapse() { {mountChildren &&

I will only render when expanded!

}
- ); + ) } ``` - diff --git a/README.md b/README.md index ef0fddf..5a10d81 100644 --- a/README.md +++ b/README.md @@ -34,11 +34,11 @@ $ npm i react-collapsed ### Simple Usage ```js -import React from 'react'; -import useCollapse from 'react-collapsed'; +import React from 'react' +import useCollapse from 'react-collapsed' function Demo() { - const { getCollapseProps, getToggleProps, isExpanded } = useCollapse(); + const { getCollapseProps, getToggleProps, isExpanded } = useCollapse() return (
@@ -47,19 +47,19 @@ function Demo() {
Collapsed content πŸ™ˆ
- ); + ) } ``` ### Control it yourself ```js -import React, { useState } from 'react'; -import useCollapse from 'react-collapsed'; +import React, { useState } from 'react' +import useCollapse from 'react-collapsed' function Demo() { - const [isExpanded, setExpanded] = useState(false); - const { getCollapseProps, getToggleProps } = useCollapse({ isExpanded }); + const [isExpanded, setExpanded] = useState(false) + const { getCollapseProps, getToggleProps } = useCollapse({ isExpanded }) return (
@@ -72,31 +72,27 @@ function Demo() {
Collapsed content πŸ™ˆ
- ); + ) } ``` ## API ```js -const { - getCollapseProps, - getToggleProps, - isExpanded, - setExpanded, -} = useCollapse({ - isExpanded: boolean, - defaultExpanded: boolean, - expandStyles: {}, - collapseStyles: {}, - collapsedHeight: 0, - easing: string, - duration: number, - onCollapseStart: func, - onCollapseEnd: func, - onExpandStart: func, - onExpandEnd: func, -}); +const { getCollapseProps, getToggleProps, isExpanded, setExpanded } = + useCollapse({ + isExpanded: boolean, + defaultExpanded: boolean, + expandStyles: {}, + collapseStyles: {}, + collapsedHeight: 0, + easing: string, + duration: number, + onCollapseStart: func, + onCollapseEnd: func, + onExpandStart: func, + onExpandEnd: func, + }) ``` ### `useCollapse` Config diff --git a/cypress.json b/cypress.json deleted file mode 100644 index e426660..0000000 --- a/cypress.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "baseUrl": "http://localhost:6006" -} diff --git a/cypress/.eslintrc.json b/cypress/.eslintrc.json deleted file mode 100644 index 96a5a52..0000000 --- a/cypress/.eslintrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "plugins": ["cypress"], - "env": { - "cypress/globals": true - } -} diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json deleted file mode 100644 index da18d93..0000000 --- a/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} \ No newline at end of file diff --git a/cypress/integration/example-spec.js b/cypress/integration/example-spec.js deleted file mode 100644 index 0ee5c97..0000000 --- a/cypress/integration/example-spec.js +++ /dev/null @@ -1,49 +0,0 @@ -import 'cypress-storybook/cypress'; - -describe('My First Test', function() { - it('Does not do much!', function() { - expect(true).to.equal(true); - }); -}); - -describe('My First Test', function() { - it('Does not do much!', function() { - expect(true).to.equal(false); - }); -}); - -describe('My First Test', function() { - it('clicks the link "type"', function() { - cy.visit('https://example.cypress.io'); - - cy.contains('type').click(); - }); -}); - -describe('RC', () => { - // Note the use of `before` - before(() => { - // Visit the storybook iframe page once per file - cy.visitStorybook(); - }); - - // Note the use of `beforeEach` - beforeEach(() => { - // The first parameter is the category. This is the `title` in CSF or the value in `storiesOf` - // The second parameter is the name of the story. This is the name of the function in CSF or the value in the `add` - // This does not refresh the page, but will unmount any previous story and use the Storybook Router API to render a fresh new story - cy.loadStory('React-Collapsed', 'Uncontrolled'); - }); - - it('toggles open and close the panel', () => { - cy.contains('Close').should('exist'); - cy.contains('Open').should('not.exist'); - cy.contains('In the morning').should('be.visible'); - - cy.contains('Close').click(); - - cy.contains('Close').should('not.exist'); - cy.contains('Open').should('exist'); - cy.contains('In the morning').should('not.be.visible'); - }); -}); diff --git a/cypress/integration/examples/actions.spec.js b/cypress/integration/examples/actions.spec.js deleted file mode 100644 index f26ba63..0000000 --- a/cypress/integration/examples/actions.spec.js +++ /dev/null @@ -1,298 +0,0 @@ -/// - -context('Actions', () => { - beforeEach(() => { - cy.visit('https://example.cypress.io/commands/actions') - }) - - // https://on.cypress.io/interacting-with-elements - - it('.type() - type into a DOM element', () => { - // https://on.cypress.io/type - cy.get('.action-email') - .type('fake@email.com').should('have.value', 'fake@email.com') - - // .type() with special character sequences - .type('{leftarrow}{rightarrow}{uparrow}{downarrow}') - .type('{del}{selectall}{backspace}') - - // .type() with key modifiers - .type('{alt}{option}') //these are equivalent - .type('{ctrl}{control}') //these are equivalent - .type('{meta}{command}{cmd}') //these are equivalent - .type('{shift}') - - // Delay each keypress by 0.1 sec - .type('slow.typing@email.com', { delay: 100 }) - .should('have.value', 'slow.typing@email.com') - - cy.get('.action-disabled') - // Ignore error checking prior to type - // like whether the input is visible or disabled - .type('disabled error checking', { force: true }) - .should('have.value', 'disabled error checking') - }) - - it('.focus() - focus on a DOM element', () => { - // https://on.cypress.io/focus - cy.get('.action-focus').focus() - .should('have.class', 'focus') - .prev().should('have.attr', 'style', 'color: orange;') - }) - - it('.blur() - blur off a DOM element', () => { - // https://on.cypress.io/blur - cy.get('.action-blur').type('About to blur').blur() - .should('have.class', 'error') - .prev().should('have.attr', 'style', 'color: red;') - }) - - it('.clear() - clears an input or textarea element', () => { - // https://on.cypress.io/clear - cy.get('.action-clear').type('Clear this text') - .should('have.value', 'Clear this text') - .clear() - .should('have.value', '') - }) - - it('.submit() - submit a form', () => { - // https://on.cypress.io/submit - cy.get('.action-form') - .find('[type="text"]').type('HALFOFF') - cy.get('.action-form').submit() - .next().should('contain', 'Your form has been submitted!') - }) - - it('.click() - click on a DOM element', () => { - // https://on.cypress.io/click - cy.get('.action-btn').click() - - // You can click on 9 specific positions of an element: - // ----------------------------------- - // | topLeft top topRight | - // | | - // | | - // | | - // | left center right | - // | | - // | | - // | | - // | bottomLeft bottom bottomRight | - // ----------------------------------- - - // clicking in the center of the element is the default - cy.get('#action-canvas').click() - - cy.get('#action-canvas').click('topLeft') - cy.get('#action-canvas').click('top') - cy.get('#action-canvas').click('topRight') - cy.get('#action-canvas').click('left') - cy.get('#action-canvas').click('right') - cy.get('#action-canvas').click('bottomLeft') - cy.get('#action-canvas').click('bottom') - cy.get('#action-canvas').click('bottomRight') - - // .click() accepts an x and y coordinate - // that controls where the click occurs :) - - cy.get('#action-canvas') - .click(80, 75) // click 80px on x coord and 75px on y coord - .click(170, 75) - .click(80, 165) - .click(100, 185) - .click(125, 190) - .click(150, 185) - .click(170, 165) - - // click multiple elements by passing multiple: true - cy.get('.action-labels>.label').click({ multiple: true }) - - // Ignore error checking prior to clicking - cy.get('.action-opacity>.btn').click({ force: true }) - }) - - it('.dblclick() - double click on a DOM element', () => { - // https://on.cypress.io/dblclick - - // Our app has a listener on 'dblclick' event in our 'scripts.js' - // that hides the div and shows an input on double click - cy.get('.action-div').dblclick().should('not.be.visible') - cy.get('.action-input-hidden').should('be.visible') - }) - - it('.rightclick() - right click on a DOM element', () => { - // https://on.cypress.io/rightclick - - // Our app has a listener on 'contextmenu' event in our 'scripts.js' - // that hides the div and shows an input on right click - cy.get('.rightclick-action-div').rightclick().should('not.be.visible') - cy.get('.rightclick-action-input-hidden').should('be.visible') - }) - - it('.check() - check a checkbox or radio element', () => { - // https://on.cypress.io/check - - // By default, .check() will check all - // matching checkbox or radio elements in succession, one after another - cy.get('.action-checkboxes [type="checkbox"]').not('[disabled]') - .check().should('be.checked') - - cy.get('.action-radios [type="radio"]').not('[disabled]') - .check().should('be.checked') - - // .check() accepts a value argument - cy.get('.action-radios [type="radio"]') - .check('radio1').should('be.checked') - - // .check() accepts an array of values - cy.get('.action-multiple-checkboxes [type="checkbox"]') - .check(['checkbox1', 'checkbox2']).should('be.checked') - - // Ignore error checking prior to checking - cy.get('.action-checkboxes [disabled]') - .check({ force: true }).should('be.checked') - - cy.get('.action-radios [type="radio"]') - .check('radio3', { force: true }).should('be.checked') - }) - - it('.uncheck() - uncheck a checkbox element', () => { - // https://on.cypress.io/uncheck - - // By default, .uncheck() will uncheck all matching - // checkbox elements in succession, one after another - cy.get('.action-check [type="checkbox"]') - .not('[disabled]') - .uncheck().should('not.be.checked') - - // .uncheck() accepts a value argument - cy.get('.action-check [type="checkbox"]') - .check('checkbox1') - .uncheck('checkbox1').should('not.be.checked') - - // .uncheck() accepts an array of values - cy.get('.action-check [type="checkbox"]') - .check(['checkbox1', 'checkbox3']) - .uncheck(['checkbox1', 'checkbox3']).should('not.be.checked') - - // Ignore error checking prior to unchecking - cy.get('.action-check [disabled]') - .uncheck({ force: true }).should('not.be.checked') - }) - - it('.select() - select an option in a