diff --git a/.eslintrc.js b/.eslintrc.js index 53b9f41c..7bb8747d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,178 +1,12 @@ -var typeScriptSettings = { +module.exports = { parser: '@typescript-eslint/parser', parserOptions: { project: './tsconfig.json', }, extends: [ - 'plugin:@typescript-eslint/recommended', - 'prettier/@typescript-eslint', - 'plugin:prettier/recommended', - 'plugin:import/typescript', + '@muban/eslint-config', ], rules: { - '@typescript-eslint/array-type': ['error', { default: 'generic', readonly: 'generic' }], - '@typescript-eslint/ban-ts-comment': 'error', - '@typescript-eslint/consistent-type-assertions': 'error', - '@typescript-eslint/explicit-member-accessibility': 'error', - '@typescript-eslint/indent': 'off', - '@typescript-eslint/naming-convention': [ - 'error', - { - selector: 'default', - format: ['camelCase'], - leadingUnderscore: 'forbid', - trailingUnderscore: 'forbid', - }, - { - selector: 'typeLike', - format: ['PascalCase'], - }, - { - selector: 'variable', - format: ['camelCase', 'UPPER_CASE', 'PascalCase'], - }, - { - selector: 'enumMember', - format: ['PascalCase'], - }, - { - selector: 'parameter', - format: ['camelCase', 'PascalCase'], - }, - ], - '@typescript-eslint/no-empty-function': 'error', - '@typescript-eslint/no-explicit-any': 'error', - '@typescript-eslint/no-inferrable-types': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { vars: 'all', args: 'after-used', ignoreRestSiblings: true, varsIgnorePattern: "Fragment" }, - ], - 'no-use-before-define': 'off', - '@typescript-eslint/no-use-before-define': ['error', { functions: false }], - '@typescript-eslint/prefer-interface': 'off', - '@typescript-eslint/prefer-readonly': 'error', - camelcase: 'off', - }, -}; - -const reactSettings = { - // parserOptions: { - // ecmaFeatures: { - // jsx: true, - // }, - // }, - // extends: ['prettier/react'], - // rules: { - // // 'react/jsx-key': 2, - // 'react/jsx-no-comment-textnodes': 2, - // 'react/jsx-no-duplicate-props': 2, - // 'react/jsx-no-target-blank': 2, - // 'react/jsx-no-undef': 2, - // 'react/jsx-uses-react': 2, - // 'react/jsx-uses-vars': 2, - // 'react/jsx-boolean-value': 'error', - // 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }], - // 'react/jsx-filename-extension': ['error', { extensions: ['.jsx', '.tsx'] }], - // }, -}; - -const mhtmlSettings = { - extends: ['plugin:lit/recommended', 'plugin:lit-a11y/recommended'], - rules: { - "lit/no-legacy-template-syntax": 'off', - "lit/no-private-properties": 'off', - "lit/no-property-change-update": 'off', - "lit/no-template-map": 'off', - "lit/binding-positions": 'off', - "lit/no-invalid-html": 'off', - - // "lit/attribute-value-entities": 'off', - // "lit/no-duplicate-template-bindings": 'off', - // "lit/no-invalid-escape-sequences": 'off', - // "lit/no-template-arrow": 'off', - // "lit/no-template-bind": 'off', - // "lit/no-value-attribute": 'off', - } -} - -module.exports = { - parserOptions: { - ecmaVersion: 2018, - sourceType: 'module', + "import/no-extraneous-dependencies": ["error", {"devDependencies": ["**/*.test.ts", "**/test-utils/**/*.ts"]}] }, - plugins: ['import', 'unicorn', 'babel', 'react', 'lit', 'lit-a11y'], - env: { - browser: true, - es6: true, - }, - globals: { - require: true, - process: true, - }, - settings: { - react: { - createClass: 'createReactClass', // Regex for Component Factory to use, - // default to "createReactClass" - pragma: 'createElement', // Pragma to use, default to "React" - version: 'detect', // React version. "detect" automatically picks the version you have installed. - // You can also use `16.0`, `16.3`, etc, if you want to override the detected value. - // default to latest and warns if missing - // It will default to "detect" in the future - flowVersion: '0.53', // Flow version - }, - }, - rules: { - 'no-console': 'warn', - }, - overrides: [ - { - files: ['*.ts'], - ...typeScriptSettings, - ...mhtmlSettings, - extends: [...typeScriptSettings.extends, ...mhtmlSettings.extends], - rules: { - ...typeScriptSettings.rules, - ...mhtmlSettings.rules, - }, - }, - { - files: ['*.tsx'], - ...typeScriptSettings, - parserOptions: { - ...typeScriptSettings.parserOptions, - ...reactSettings.parserOptions, - }, - rules: { - ...typeScriptSettings.rules, - ...reactSettings.rules, - '@typescript-eslint/naming-convention': [ - 'error', - { - selector: 'default', - format: ['camelCase'], - leadingUnderscore: 'forbid', - trailingUnderscore: 'forbid', - }, - { - selector: 'typeLike', - format: ['PascalCase'], - }, - { - selector: 'variable', - // Exception for FunctionComponents - format: ['camelCase', 'PascalCase', 'UPPER_CASE'], - }, - { - selector: 'function', - // Exception for FunctionComponents - format: ['camelCase', 'PascalCase'], - }, - { - selector: 'enumMember', - format: ['PascalCase'], - }, - ], - }, - }, - ], }; diff --git a/.github/workflows/bump-version-and-publish.yml b/.github/workflows/bump-version-and-publish.yml new file mode 100644 index 00000000..5bf22c45 --- /dev/null +++ b/.github/workflows/bump-version-and-publish.yml @@ -0,0 +1,52 @@ +# NOTE: taken from https://github.com/MylesBorins/node-osc/blob/main/.github/workflows/bump-version.yml + +name: Bump version, Tag & Publish + +on: + workflow_dispatch: + inputs: + version: + description: 'Semver type of new version (major / minor / patch / prerelease)' + required: true + prereleaseid: + description: 'Prerelease id (rc)' + default: '' + +jobs: + bump-version: + runs-on: ubuntu-latest + + steps: + - name: Check out source + uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '16' + cache: 'npm' + + - name: Install npm packages + run: npm ci + + - name: Setup Git + run: | + git config user.name github-actions + git config user.email github-actions@github.com + + - name: bump version + run: | + npm version ${{ github.event.inputs.version }} --no-git-tag-version --preid ${{ github.event.inputs.prereleaseid }} + git add . + git commit -m "v$(npm pkg get version | tr -d '"')" + git tag $(npm pkg get version | tr -d '"') -m "v$(npm pkg get version | tr -d '"')" + + - name: publish + run: | + npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN} + npm publish + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Push latest version + run: git push origin main --follow-tags diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml new file mode 100644 index 00000000..abd3c84c --- /dev/null +++ b/.github/workflows/update-docs.yml @@ -0,0 +1,35 @@ +name: Update Docs + +on: + push: + branches: [main] + +jobs: + update-docs: + runs-on: ubuntu-latest + + steps: + - name: Check out source + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '16' + cache: 'npm' + + - name: Install npm packages + run: npm ci + + - name: Build Docs + run: npm run docs:build + + - name: Deploy to GitHub Pages + uses: crazy-max/ghaction-github-pages@v2 + with: + target_branch: gh-pages + build_dir: docs/.vuepress/dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index d81e0c85..beb2f569 100644 --- a/.gitignore +++ b/.gitignore @@ -33,10 +33,8 @@ yarn-error.log* .eslintcache # npm publish artifects -/lib /dist -index.js -index.d.ts +/types /tmp /decl diff --git a/.node-version b/.node-version index 8351c193..b6a7d89c 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -14 +16 diff --git a/.nvmrc b/.nvmrc index 8351c193..b6a7d89c 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -14 +16 diff --git a/README.md b/README.md index c1940bc3..e8378631 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ module.exports = { Create your story file: ```ts -import type { Story } from '@muban/storybook/dist/client/preview/types-6-0'; +import type { Story } from '@muban/storybook/types-6-0'; export default { title: 'MyComponent', diff --git a/cypress.json b/cypress.json deleted file mode 100644 index 0967ef42..00000000 --- a/cypress.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json deleted file mode 100644 index da18d935..00000000 --- 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/fixtures/profile.json b/cypress/fixtures/profile.json deleted file mode 100644 index b6c355ca..00000000 --- a/cypress/fixtures/profile.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": 8739, - "name": "Jane", - "email": "jane@example.com" -} \ No newline at end of file diff --git a/cypress/fixtures/users.json b/cypress/fixtures/users.json deleted file mode 100644 index 79b699aa..00000000 --- a/cypress/fixtures/users.json +++ /dev/null @@ -1,232 +0,0 @@ -[ - { - "id": 1, - "name": "Leanne Graham", - "username": "Bret", - "email": "Sincere@april.biz", - "address": { - "street": "Kulas Light", - "suite": "Apt. 556", - "city": "Gwenborough", - "zipcode": "92998-3874", - "geo": { - "lat": "-37.3159", - "lng": "81.1496" - } - }, - "phone": "1-770-736-8031 x56442", - "website": "hildegard.org", - "company": { - "name": "Romaguera-Crona", - "catchPhrase": "Multi-layered client-server neural-net", - "bs": "harness real-time e-markets" - } - }, - { - "id": 2, - "name": "Ervin Howell", - "username": "Antonette", - "email": "Shanna@melissa.tv", - "address": { - "street": "Victor Plains", - "suite": "Suite 879", - "city": "Wisokyburgh", - "zipcode": "90566-7771", - "geo": { - "lat": "-43.9509", - "lng": "-34.4618" - } - }, - "phone": "010-692-6593 x09125", - "website": "anastasia.net", - "company": { - "name": "Deckow-Crist", - "catchPhrase": "Proactive didactic contingency", - "bs": "synergize scalable supply-chains" - } - }, - { - "id": 3, - "name": "Clementine Bauch", - "username": "Samantha", - "email": "Nathan@yesenia.net", - "address": { - "street": "Douglas Extension", - "suite": "Suite 847", - "city": "McKenziehaven", - "zipcode": "59590-4157", - "geo": { - "lat": "-68.6102", - "lng": "-47.0653" - } - }, - "phone": "1-463-123-4447", - "website": "ramiro.info", - "company": { - "name": "Romaguera-Jacobson", - "catchPhrase": "Face to face bifurcated interface", - "bs": "e-enable strategic applications" - } - }, - { - "id": 4, - "name": "Patricia Lebsack", - "username": "Karianne", - "email": "Julianne.OConner@kory.org", - "address": { - "street": "Hoeger Mall", - "suite": "Apt. 692", - "city": "South Elvis", - "zipcode": "53919-4257", - "geo": { - "lat": "29.4572", - "lng": "-164.2990" - } - }, - "phone": "493-170-9623 x156", - "website": "kale.biz", - "company": { - "name": "Robel-Corkery", - "catchPhrase": "Multi-tiered zero tolerance productivity", - "bs": "transition cutting-edge web services" - } - }, - { - "id": 5, - "name": "Chelsey Dietrich", - "username": "Kamren", - "email": "Lucio_Hettinger@annie.ca", - "address": { - "street": "Skiles Walks", - "suite": "Suite 351", - "city": "Roscoeview", - "zipcode": "33263", - "geo": { - "lat": "-31.8129", - "lng": "62.5342" - } - }, - "phone": "(254)954-1289", - "website": "demarco.info", - "company": { - "name": "Keebler LLC", - "catchPhrase": "User-centric fault-tolerant solution", - "bs": "revolutionize end-to-end systems" - } - }, - { - "id": 6, - "name": "Mrs. Dennis Schulist", - "username": "Leopoldo_Corkery", - "email": "Karley_Dach@jasper.info", - "address": { - "street": "Norberto Crossing", - "suite": "Apt. 950", - "city": "South Christy", - "zipcode": "23505-1337", - "geo": { - "lat": "-71.4197", - "lng": "71.7478" - } - }, - "phone": "1-477-935-8478 x6430", - "website": "ola.org", - "company": { - "name": "Considine-Lockman", - "catchPhrase": "Synchronised bottom-line interface", - "bs": "e-enable innovative applications" - } - }, - { - "id": 7, - "name": "Kurtis Weissnat", - "username": "Elwyn.Skiles", - "email": "Telly.Hoeger@billy.biz", - "address": { - "street": "Rex Trail", - "suite": "Suite 280", - "city": "Howemouth", - "zipcode": "58804-1099", - "geo": { - "lat": "24.8918", - "lng": "21.8984" - } - }, - "phone": "210.067.6132", - "website": "elvis.io", - "company": { - "name": "Johns Group", - "catchPhrase": "Configurable multimedia task-force", - "bs": "generate enterprise e-tailers" - } - }, - { - "id": 8, - "name": "Nicholas Runolfsdottir V", - "username": "Maxime_Nienow", - "email": "Sherwood@rosamond.me", - "address": { - "street": "Ellsworth Summit", - "suite": "Suite 729", - "city": "Aliyaview", - "zipcode": "45169", - "geo": { - "lat": "-14.3990", - "lng": "-120.7677" - } - }, - "phone": "586.493.6943 x140", - "website": "jacynthe.com", - "company": { - "name": "Abernathy Group", - "catchPhrase": "Implemented secondary concept", - "bs": "e-enable extensible e-tailers" - } - }, - { - "id": 9, - "name": "Glenna Reichert", - "username": "Delphine", - "email": "Chaim_McDermott@dana.io", - "address": { - "street": "Dayna Park", - "suite": "Suite 449", - "city": "Bartholomebury", - "zipcode": "76495-3109", - "geo": { - "lat": "24.6463", - "lng": "-168.8889" - } - }, - "phone": "(775)976-6794 x41206", - "website": "conrad.com", - "company": { - "name": "Yost and Sons", - "catchPhrase": "Switchable contextually-based project", - "bs": "aggregate real-time technologies" - } - }, - { - "id": 10, - "name": "Clementina DuBuque", - "username": "Moriah.Stanton", - "email": "Rey.Padberg@karina.biz", - "address": { - "street": "Kattie Turnpike", - "suite": "Suite 198", - "city": "Lebsackbury", - "zipcode": "31428-2261", - "geo": { - "lat": "-38.2386", - "lng": "57.2232" - } - }, - "phone": "024-648-3804", - "website": "ambrose.net", - "company": { - "name": "Hoeger LLC", - "catchPhrase": "Centralized empowering task-force", - "bs": "target end-to-end models" - } - } -] \ No newline at end of file diff --git a/cypress/integration/components.spec.js b/cypress/integration/components.spec.js deleted file mode 100644 index 60ad609e..00000000 --- a/cypress/integration/components.spec.js +++ /dev/null @@ -1,39 +0,0 @@ -function getVariations(module) { - return Object.keys(module.default); -} - -context('Components', () => { - beforeEach(() => { - cy.visit('http://localhost:8080'); - }); - - const componentName = 'toggle-expand'; - describe(`Test - ${componentName}`, () => { - const variations = getVariations(require(`../../examples/src/components/toggle-expand/meta`)); - - beforeEach(() => { - cy.get(`.component-list li a:contains("${componentName}")`).click(); - }); - - Cypress._.times(variations.length, (i) => { - const variationValue = variations[i]; - describe(variationValue, () => { - it(`[${variationValue}] .should() - expand and collapse when clicking button for variation`, () => { - cy.get('#componentVariation').select(variations[i]); - - cy.get('[data-ref=expand-content]').should('have.attr', 'style', 'display: none;'); - - cy.get('[data-ref=expand-button]').click(); - cy.get('[data-ref=expand-content]').should('have.attr', 'style', 'display: block;'); - cy.get('[data-ref=expand-button]').click(); - cy.get('[data-ref=expand-content]').should('have.attr', 'style', 'display: none;'); - - cy.get('[data-ref=expand-button]').click(); - cy.get('[data-ref=expand-content]').should('have.attr', 'style', 'display: block;'); - cy.get('[data-ref=expand-button]').click(); - cy.get('[data-ref=expand-content]').should('have.attr', 'style', 'display: none;'); - }) - }) - }); - }); -}); diff --git a/cypress/integration/examples/actions.spec.js b/cypress/integration/examples/actions.spec.js deleted file mode 100644 index ef430ed8..00000000 --- a/cypress/integration/examples/actions.spec.js +++ /dev/null @@ -1,299 +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