├── .nvmrc
├── src
├── lib
│ ├── index.ts
│ └── CounterDemo
│ │ ├── index.ts
│ │ ├── __snapshots__
│ │ ├── useLogic.spec.ts.snap
│ │ └── Counter.spec.tsx.snap
│ │ ├── useLogic.ts
│ │ ├── Counter.mdx
│ │ ├── Counter.stories.ts
│ │ ├── Counter.module.css
│ │ ├── Counter.tsx
│ │ ├── useLogic.spec.ts
│ │ └── Counter.spec.tsx
├── vite-env.d.ts
├── setupTests.ts
├── env
│ └── App
│ │ ├── App.tsx
│ │ └── index.css
└── main.tsx
├── .husky
├── pre-commit
└── pre-push
├── templates
└── Component
│ ├── index.ts
│ ├── useLogic.ts
│ ├── TemplateName.mdx
│ ├── TemplateName.module.css
│ ├── TemplateName.tsx
│ ├── TemplateName.stories.tsx
│ ├── useLogic.spec.ts
│ └── TemplateName.spec.tsx
├── design
├── logo.ai
├── logo.jpg
└── logo.png
├── .lintstagedrc
├── tsconfig.node.json
├── tsconfig.linter.json
├── .storybook
├── preview.ts
└── main.ts
├── .gitignore
├── index.html
├── renovate.json
├── jest.config.mjs
├── .stylelintrc
├── tsconfig.json
├── generate-react-cli.json
├── LICENSE
├── public
└── vite.svg
├── vite.config.ts
├── .github
└── workflows
│ ├── merge-jobs.yml
│ ├── pull-request-jobs.yml
│ └── pages.yml
├── package.json
├── README.md
├── eslint.config.js
└── .editorconfig
/.nvmrc:
--------------------------------------------------------------------------------
1 | 20
2 |
--------------------------------------------------------------------------------
/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | export {Counter} from './CounterDemo';
2 |
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | pnpm run lint-staged
2 | pnpm run lint:types
3 |
--------------------------------------------------------------------------------
/.husky/pre-push:
--------------------------------------------------------------------------------
1 | CI=true pnpm run test --passWithNoTests --silent
2 |
--------------------------------------------------------------------------------
/src/lib/CounterDemo/index.ts:
--------------------------------------------------------------------------------
1 | export {Counter} from './Counter.tsx';
2 |
--------------------------------------------------------------------------------
/templates/Component/index.ts:
--------------------------------------------------------------------------------
1 | export {TemplateName} from './TemplateName.tsx';
2 |
--------------------------------------------------------------------------------
/design/logo.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morewings/react-library-template/HEAD/design/logo.ai
--------------------------------------------------------------------------------
/design/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morewings/react-library-template/HEAD/design/logo.jpg
--------------------------------------------------------------------------------
/design/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morewings/react-library-template/HEAD/design/logo.png
--------------------------------------------------------------------------------
/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "*.{js,ts,tsx}": [
3 | "eslint --fix"
4 | ],
5 | "*.css": [
6 | "stylelint --fix --quiet"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // learn more: https://github.com/testing-library/jest-dom
3 | import '@testing-library/jest-dom';
4 |
--------------------------------------------------------------------------------
/src/lib/CounterDemo/__snapshots__/useLogic.spec.ts.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`lib > Counter > useLogic renders 1`] = `
4 | {
5 | "count": 0,
6 | "incrementCount": [Function],
7 | }
8 | `;
9 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/src/env/App/App.tsx:
--------------------------------------------------------------------------------
1 | import type {FC} from 'react';
2 |
3 | import {Counter} from '@/lib';
4 | import './index.css';
5 |
6 | const App: FC = () => {
7 | return (
8 |
9 |
10 |
11 | );
12 | };
13 |
14 | export default App;
15 |
--------------------------------------------------------------------------------
/tsconfig.linter.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends" : "./tsconfig.json",
3 | "include": [
4 | "**/*.stories.*",
5 | "*.config.*",
6 | "src",
7 | ".storybook/*.ts",
8 | ".eslintrc.cjs",
9 | "templates/**/*.ts",
10 | "templates/**/*.tsx"
11 | ],
12 | "exclude": ["./dist/**"]
13 | }
14 |
--------------------------------------------------------------------------------
/src/lib/CounterDemo/useLogic.ts:
--------------------------------------------------------------------------------
1 | import {useState} from 'react';
2 |
3 | const useLogic = (initialState: number) => {
4 | const [count, setCount] = useState(initialState);
5 | return {
6 | count,
7 | incrementCount: () => setCount(count + 1),
8 | };
9 | };
10 |
11 | export default useLogic;
12 |
--------------------------------------------------------------------------------
/templates/Component/useLogic.ts:
--------------------------------------------------------------------------------
1 | import {useState} from 'react';
2 |
3 | const useLogic = (initialState: number) => {
4 | const [count, setCount] = useState(initialState);
5 | return {
6 | count,
7 | incrementCount: () => setCount(count + 1),
8 | };
9 | };
10 |
11 | export default useLogic;
12 |
--------------------------------------------------------------------------------
/.storybook/preview.ts:
--------------------------------------------------------------------------------
1 | import type {Preview} from '@storybook/react-vite';
2 |
3 | const preview: Preview = {
4 | parameters: {
5 | controls: {
6 | matchers: {
7 | color: /(background|color)$/i,
8 | date: /Date$/i,
9 | },
10 | },
11 | },
12 | };
13 |
14 | export default preview;
15 |
--------------------------------------------------------------------------------
/src/env/App/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | text-rendering: optimizelegibility;
4 | }
5 |
6 | body {
7 | align-items: center;
8 | display: flex;
9 | flex-direction: row;
10 | justify-content: center;
11 | margin: 0;
12 | min-height: 100vh;
13 | min-width: 320px;
14 | }
15 |
--------------------------------------------------------------------------------
/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 |
4 | import App from '@/env/App/App.tsx';
5 |
6 | // eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
7 | ReactDOM.createRoot(document.getElementById('root')!).render(
8 |
9 |
10 |
11 | );
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 | storybook-static
26 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:recommended"
5 | ],
6 | "schedule": [
7 | "before 4am on the first day of the month"
8 | ],
9 | "hostRules": [
10 | {
11 | "matchHost": "api.github.com",
12 | "concurrentRequestLimit": 23
13 | }
14 | ],
15 | "baseBranchPatterns": [
16 | "master",
17 | "tailwind"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/templates/Component/TemplateName.mdx:
--------------------------------------------------------------------------------
1 | import { Meta, ArgTypes, Story, Canvas, Source, Markdown, Primary } from "@storybook/addon-docs/blocks";
2 | import {TemplateName} from './TemplateName.tsx';
3 | import * as TemplateNameStories from "./TemplateName.stories.tsx";
4 |
5 |
6 |
7 | # TemplateName
8 |
9 | Text tba.
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/lib/CounterDemo/__snapshots__/Counter.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`lib > Counter renders without crashing 1`] = `
4 |
5 |
6 |
7 | Counter
8 |
9 |
14 |
15 | Total value:
16 |
17 | 6
18 |
19 |
20 |
21 |
22 | `;
23 |
--------------------------------------------------------------------------------
/jest.config.mjs:
--------------------------------------------------------------------------------
1 | import {kitchen} from 'alias-kitchen';
2 |
3 | export default {
4 | preset: 'ts-jest',
5 | testEnvironment: 'jest-environment-jsdom',
6 | transform: {
7 | '^.+\\.tsx?$': 'ts-jest',
8 | // process `*.tsx` files with `ts-jest`
9 | },
10 | moduleNameMapper: {
11 | ...kitchen({recipe: 'jest'}),
12 | '\\.(gif|ttf|eot|svg|png|jpg)$': 'identity-obj-proxy',
13 | '\\.css$': 'identity-obj-proxy',
14 | },
15 | modulePathIgnorePatterns: ['/templates/'],
16 | setupFilesAfterEnv: ['/src/setupTests.ts'],
17 | };
18 |
--------------------------------------------------------------------------------
/src/lib/CounterDemo/Counter.mdx:
--------------------------------------------------------------------------------
1 | import { Meta, ArgTypes, Story } from "@storybook/addon-docs/blocks";
2 | import * as CounterStories from './Counter.stories';
3 | import { Counter } from "./Counter";
4 |
5 |
6 |
7 | # Example Component Demo
8 |
9 | ## Counter props
10 |
11 |
12 |
13 | ## Description
14 |
15 | `Counter` component provides user basic interface to increment counter by one.
16 |
17 | ## Demo
18 |
19 |
20 |
21 | ## With initial value
22 |
23 | This is another example with initial value
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "stylelint-config-standard",
4 | "stylelint-prettier/recommended"
5 | ],
6 | "rules": {
7 | "function-calc-no-unspaced-operator": true,
8 | "order/order": [
9 | "custom-properties",
10 | "declarations"
11 | ],
12 | "order/properties-alphabetical-order": true,
13 | "property-no-vendor-prefix": true,
14 | "media-feature-name-no-vendor-prefix": true,
15 | "at-rule-no-vendor-prefix": true,
16 | "selector-no-vendor-prefix": true,
17 | "max-nesting-depth": 3,
18 | "selector-max-compound-selectors": 5
19 | },
20 | "plugins": [
21 | "stylelint-order"
22 | ],
23 | "ignoreFiles": ["**/*.snap"]
24 | }
25 |
--------------------------------------------------------------------------------
/.storybook/main.ts:
--------------------------------------------------------------------------------
1 | import type {StorybookConfig} from '@storybook/react-vite';
2 | import {withoutVitePlugins} from '@storybook/builder-vite';
3 |
4 | const config: StorybookConfig = {
5 | stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
6 | addons: ['@storybook/addon-links', '@storybook/addon-docs'],
7 | framework: {
8 | name: '@storybook/react-vite',
9 | options: {},
10 | },
11 | async viteFinal(config) {
12 | return {
13 | ...config,
14 | plugins: await withoutVitePlugins(config.plugins, ['vite:dts']),
15 | };
16 | },
17 | typescript: {
18 | reactDocgen: 'react-docgen-typescript',
19 | },
20 | };
21 | export default config;
22 |
--------------------------------------------------------------------------------
/src/lib/CounterDemo/Counter.stories.ts:
--------------------------------------------------------------------------------
1 | import type {Meta, StoryObj} from '@storybook/react-vite';
2 |
3 | import {Counter} from './Counter';
4 |
5 | const meta = {
6 | title: 'Example/Counter',
7 | component: Counter,
8 | parameters: {
9 | // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
10 | layout: 'fullscreen',
11 | },
12 | } as Meta;
13 |
14 | export default meta;
15 | type Story = StoryObj;
16 |
17 | export const ExampleCounter: Story = {
18 | args: {
19 | initialValue: 0,
20 | },
21 | };
22 |
23 | export const ExampleCounterWithInitialValue: Story = {
24 | args: {
25 | initialValue: 11,
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/src/lib/CounterDemo/Counter.module.css:
--------------------------------------------------------------------------------
1 | .counter {
2 | border: 1px solid lightgray;
3 | font-family: sans-serif;
4 | margin: 36px 24px;
5 | padding: 24px;
6 | text-align: center;
7 | width: 240px;
8 | }
9 |
10 | .header {
11 | font-size: 24px;
12 | font-weight: normal;
13 | margin: 0 0 12px;
14 | }
15 |
16 | .button {
17 | background: lightseagreen;
18 | border: none;
19 | border-radius: 5px;
20 | color: white;
21 | cursor: pointer;
22 | display: block;
23 | font-size: 16px;
24 | margin: 0 auto 24px;
25 | padding: 12px 24px;
26 | text-shadow: 1px 1px 1px rgb(0 0 0 / 50%);
27 | }
28 |
29 | .button:active {
30 | left: 1px;
31 | position: relative;
32 | top: 1px;
33 | }
34 |
--------------------------------------------------------------------------------
/templates/Component/TemplateName.module.css:
--------------------------------------------------------------------------------
1 | .template-name {
2 | border: 1px solid lightgray;
3 | font-family: sans-serif;
4 | margin: 36px 24px;
5 | padding: 24px;
6 | text-align: center;
7 | width: 240px;
8 | }
9 |
10 | .header {
11 | font-size: 24px;
12 | font-weight: normal;
13 | margin: 0 0 12px;
14 | }
15 |
16 | .button {
17 | background: lightseagreen;
18 | border: none;
19 | border-radius: 5px;
20 | color: white;
21 | cursor: pointer;
22 | display: block;
23 | font-size: 16px;
24 | margin: 0 auto 24px;
25 | padding: 12px 24px;
26 | text-shadow: 1px 1px 1px rgb(0 0 0 / 50%);
27 | }
28 |
29 | .button:active {
30 | left: 1px;
31 | position: relative;
32 | top: 1px;
33 | }
34 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 | "allowSyntheticDefaultImports": true,
9 |
10 | /* Bundler mode */
11 | "moduleResolution": "bundler",
12 | "allowImportingTsExtensions": true,
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "noEmit": true,
16 | "jsx": "react-jsx",
17 |
18 | /* Linting */
19 | "strict": true,
20 | "noUnusedLocals": true,
21 | "noUnusedParameters": true,
22 | "noFallthroughCasesInSwitch": true,
23 |
24 | /* Aliases */
25 | "paths": {
26 | "@/*": ["./src/*"]
27 | }
28 | },
29 | "include": ["src", "templates/**/*.ts", "templates/**/*.tsx"],
30 | "exclude": ["**/*.stories.*"],
31 | "references": [{ "path": "./tsconfig.node.json" }]
32 | }
33 |
--------------------------------------------------------------------------------
/generate-react-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "usesTypeScript": true,
3 | "usesCssModule": true,
4 | "cssPreprocessor": "css",
5 | "testLibrary": "Testing Library",
6 | "component": {
7 | "default": {
8 | "path": "src/lib",
9 | "withLazy": false,
10 | "withStory": true,
11 | "withStyle": true,
12 | "withTest": false,
13 | "withIndex": true,
14 | "withMdx": true,
15 | "withHook": true,
16 | "withHookTest": true,
17 | "customTemplates": {
18 | "component": "templates/Component/TemplateName.tsx",
19 | "style": "templates/Component/TemplateName.module.css",
20 | "story": "templates/Component/TemplateName.stories.tsx",
21 | "index": "templates/Component/index.ts",
22 | "mdx": "templates/Component/TemplateName.mdx",
23 | "test": "templates/Component/TemplateName.spec.tsx",
24 | "hook": "templates/Component/useLogic.ts",
25 | "hookTest": "templates/Component/useLogic.spec.ts"
26 | }
27 | }
28 | },
29 | "usesStyledComponents": false
30 | }
31 |
--------------------------------------------------------------------------------
/src/lib/CounterDemo/Counter.tsx:
--------------------------------------------------------------------------------
1 | import type {FC} from 'react';
2 | import {useEffect} from 'react';
3 | import {throttle} from 'lodash';
4 |
5 | import classes from './Counter.module.css';
6 | import useLogic from './useLogic';
7 |
8 | export type Props = {
9 | /** Set initial value */
10 | initialValue?: number;
11 | };
12 |
13 | export const Counter: FC = ({initialValue = 0}) => {
14 | const {count, incrementCount} = useLogic(initialValue);
15 |
16 | useEffect(() => {
17 | const runner = throttle(() => {
18 | console.log('throttle');
19 | }, 10);
20 | runner();
21 | }, []);
22 |
23 | return (
24 |
25 |
Counter
26 |
29 |
30 | Total value: {count}
31 |
32 |
33 | );
34 | };
35 |
--------------------------------------------------------------------------------
/templates/Component/TemplateName.tsx:
--------------------------------------------------------------------------------
1 | import type {FC} from 'react';
2 | import {useEffect} from 'react';
3 | import {throttle} from 'lodash';
4 |
5 | import classes from './TemplateName.module.css';
6 | import useLogic from './useLogic';
7 |
8 | export type Props = {
9 | /** Set initial value */
10 | initialValue?: number;
11 | };
12 |
13 | export const TemplateName: FC = ({initialValue = 0}) => {
14 | const {count, incrementCount} = useLogic(initialValue);
15 |
16 | useEffect(() => {
17 | const runner = throttle(() => {
18 | console.log('throttle');
19 | }, 10);
20 | runner();
21 | }, []);
22 | return (
23 |
24 |
Counter
25 |
28 |
29 | Total value: {count}
30 |
31 |
32 | );
33 | };
34 |
--------------------------------------------------------------------------------
/templates/Component/TemplateName.stories.tsx:
--------------------------------------------------------------------------------
1 | import type {Meta, StoryObj} from '@storybook/react-vite';
2 |
3 | import {TemplateName} from './TemplateName';
4 |
5 | const meta = {
6 | title: 'Example/TemplateName',
7 | component: TemplateName,
8 | parameters: {
9 | // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
10 | layout: 'fullscreen',
11 | },
12 | } as Meta;
13 |
14 | export default meta;
15 | type Story = StoryObj;
16 |
17 | export const Primary: Story = {
18 | render: args => {
19 | return ;
20 | },
21 | args: {},
22 | };
23 |
24 | export const WithCode: Story = {
25 | render: args => {
26 | // here comes the code
27 | return ;
28 | },
29 | };
30 |
31 | WithCode.args = {};
32 |
33 | WithCode.argTypes = {};
34 |
35 | WithCode.parameters = {
36 | docs: {
37 | source: {
38 | language: 'tsx',
39 | type: 'code',
40 | },
41 | },
42 | };
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Dima Vyshniakov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/lib/CounterDemo/useLogic.spec.ts:
--------------------------------------------------------------------------------
1 | import {renderHook, act} from '@testing-library/react';
2 |
3 | import useLogic from './useLogic';
4 |
5 | describe('lib > Counter > useLogic', () => {
6 | const initialValue = 0;
7 | it('renders', () => {
8 | /**
9 | * Render hook, using testing-library utility
10 | * @see https://testing-library.com/docs/react-testing-library/api#renderhook
11 | */
12 | const {result} = renderHook(() => useLogic(initialValue));
13 |
14 | expect(result.current).toMatchSnapshot();
15 | });
16 | it('increments value', () => {
17 | /**
18 | * Render hook, using testing-library utility
19 | * @see https://testing-library.com/docs/react-testing-library/api#renderhook
20 | */
21 | const {result} = renderHook(() => useLogic(initialValue));
22 |
23 | /**
24 | * Wrap state update with act
25 | * @see https://fb.me/react-wrap-tests-with-act
26 | */
27 | act(() => {
28 | result.current.incrementCount();
29 | });
30 |
31 | expect(result.current.count).toBe(initialValue + 1);
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/templates/Component/useLogic.spec.ts:
--------------------------------------------------------------------------------
1 | import {renderHook, act} from '@testing-library/react';
2 |
3 | import useLogic from './useLogic';
4 |
5 | describe('lib > Counter > useLogic', () => {
6 | const initialValue = 0;
7 | it('renders', () => {
8 | /**
9 | * Render hook, using testing-library utility
10 | * @see https://testing-library.com/docs/react-testing-library/api#renderhook
11 | */
12 | const {result} = renderHook(() => useLogic(initialValue));
13 |
14 | expect(result.current).toMatchSnapshot();
15 | });
16 | it('increments value', () => {
17 | /**
18 | * Render hook, using testing-library utility
19 | * @see https://testing-library.com/docs/react-testing-library/api#renderhook
20 | */
21 | const {result} = renderHook(() => useLogic(initialValue));
22 |
23 | /**
24 | * Wrap state update with act
25 | * @see https://fb.me/react-wrap-tests-with-act
26 | */
27 | act(() => {
28 | result.current.incrementCount();
29 | });
30 |
31 | expect(result.current.count).toBe(initialValue + 1);
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import {resolve} from 'path';
2 |
3 | import {defineConfig} from 'vite';
4 | import react from '@vitejs/plugin-react';
5 | import {kitchen} from 'alias-kitchen';
6 | import external from '@yelo/rollup-node-external';
7 | import dts from 'vite-plugin-dts';
8 | import postcssPresetEnv from 'postcss-preset-env';
9 |
10 | // https://vitejs.dev/config/
11 | export default defineConfig({
12 | resolve: {
13 | alias: kitchen({recipe: 'rollup'}),
14 | },
15 | plugins: [react(), dts({rollupTypes: true, exclude: ['**/*.stories.(ts|tsx)']})],
16 | build: {
17 | sourcemap: true,
18 | lib: {
19 | // Could also be a dictionary or array of multiple entry points
20 | entry: resolve(__dirname, 'src/lib/index.ts'),
21 | name: 'Library name',
22 | // the proper extensions will be added
23 | fileName: 'index',
24 | },
25 | rollupOptions: {
26 | // make sure to externalize deps that shouldn't be bundled
27 | // into your library
28 | external: external(),
29 | output: {
30 | // Provide global variables to use in the UMD build
31 | // for externalized deps
32 | globals: {
33 | react: 'React',
34 | },
35 | },
36 | },
37 | },
38 | css: {
39 | modules: {
40 | localsConvention: 'camelCase',
41 | },
42 | postcss: {
43 | plugins: [postcssPresetEnv({stage: 1})],
44 | },
45 | },
46 | });
47 |
--------------------------------------------------------------------------------
/.github/workflows/merge-jobs.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3 |
4 | name: Post-merge tasks
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 |
10 | jobs:
11 | build-publish:
12 |
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - name: Cancel Workflow Action
17 | uses: styfle/cancel-workflow-action@0.12.1
18 | with:
19 | access_token: ${{ github.token }}
20 |
21 | - name: Checkout
22 | uses: actions/checkout@v4
23 |
24 | - name: Read .nvmrc
25 | run: echo "NVMRC=$(cat .nvmrc)" >> $GITHUB_ENV
26 | id: nvm
27 |
28 | - name: Use Node.js ${{ env.NVMRC }}
29 | uses: actions/setup-node@v4
30 | with:
31 | node-version: ${{ env.NVMRC }}
32 |
33 | - name: Install pnpm
34 | uses: pnpm/action-setup@v4
35 | with:
36 | version: 10
37 | run_install: false
38 |
39 | - name: Get pnpm store directory
40 | shell: bash
41 | run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
42 |
43 | - name: Setup pnpm cache
44 | uses: actions/cache@v4
45 | with:
46 | path: ${{ env.STORE_PATH }}
47 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
48 | restore-keys: |
49 | ${{ runner.os }}-pnpm-store-
50 |
51 | - name: Run merge tasks
52 | run: |
53 | pnpm install
54 |
55 | # - name: Publish NPM package
56 | # uses: JS-DevTools/npm-publish@v3
57 | # with:
58 | # token: ${{ secrets.NPM_TOKEN }}
59 |
--------------------------------------------------------------------------------
/.github/workflows/pull-request-jobs.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3 |
4 | name: Node.js CI
5 |
6 | on:
7 | pull_request:
8 | branches: [ master ]
9 |
10 | jobs:
11 | lint-test:
12 |
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - name: Cancel Workflow Action
17 | uses: styfle/cancel-workflow-action@0.12.1
18 | with:
19 | access_token: ${{ github.token }}
20 |
21 | - name: Checkout
22 | uses: actions/checkout@v4
23 |
24 | - name: Read .nvmrc
25 | run: echo "NVMRC=$(cat .nvmrc)" >> $GITHUB_ENV
26 | id: nvm
27 |
28 | - name: Use Node.js ${{ env.NVMRC }}
29 | uses: actions/setup-node@v4
30 | with:
31 | node-version: ${{ env.NVMRC }}
32 |
33 | - name: Install pnpm
34 | uses: pnpm/action-setup@v4
35 | with:
36 | version: 10
37 | run_install: false
38 |
39 | - name: Get pnpm store directory
40 | shell: bash
41 | run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
42 |
43 | - name: Setup pnpm cache
44 | uses: actions/cache@v4
45 | with:
46 | path: ${{ env.STORE_PATH }}
47 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
48 | restore-keys: |
49 | ${{ runner.os }}-pnpm-store-
50 |
51 | - name: Run test tasks
52 | run: |
53 | pnpm install
54 | pnpm run lint:code --quiet
55 | pnpm run lint:style --quiet
56 | pnpm run test --silent
57 | pnpm run start:docs --smoke-test --quiet
58 | pnpm run build
59 | pnpm run generate:component Foo --dry-run
60 |
--------------------------------------------------------------------------------
/src/lib/CounterDemo/Counter.spec.tsx:
--------------------------------------------------------------------------------
1 | import {render, fireEvent} from '@testing-library/react';
2 |
3 | import {Counter} from './Counter';
4 |
5 | describe('lib > Counter', () => {
6 | /**
7 | * Jest hook which runs before each test,
8 | * @see https://jestjs.io/docs/en/api#beforeeachfn-timeout
9 | */
10 | beforeEach(() => {});
11 |
12 | it('renders without crashing', () => {
13 | /**
14 | * `asFragment`:
15 | * @see https://testing-library.com/docs/react-testing-library/api#asfragment
16 | * `baseElement`:
17 | * @see https://testing-library.com/docs/react-testing-library/api#baseelement
18 | */
19 | const {asFragment, baseElement} = render();
20 |
21 | /**
22 | * Basic snapshot test to make sure, that rendered component
23 | * matches expected footprint.
24 | */
25 | expect(asFragment()).toMatchSnapshot();
26 |
27 | /** More precise test for counter value */
28 | expect(baseElement.querySelector('strong')!.textContent).toBe('6'); // 6 is value we expect, we need to convert Number to String, because HTMLElement textContent method returns string value
29 | });
30 |
31 | it('changes counter value on button click', () => {
32 | const value = 1;
33 |
34 | /**
35 | * `getByRole`:
36 | * @see https://testing-library.com/docs/dom-testing-library/api-queries#byrole
37 | */
38 | const {getByRole, baseElement} = render();
39 |
40 | /**
41 | * Search for the button and make testing library click on it
42 | * @see https://testing-library.com/docs/react-testing-library/cheatsheet#events
43 | */
44 | fireEvent.click(getByRole('button'));
45 |
46 | /** Check if counter was incremented */
47 | expect(baseElement.querySelector('strong')!.textContent).toBe(`${value + 1}`);
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/templates/Component/TemplateName.spec.tsx:
--------------------------------------------------------------------------------
1 | import {render, fireEvent} from '@testing-library/react';
2 |
3 | import {TemplateName} from './TemplateName';
4 |
5 | describe('lib > TemplateName', () => {
6 | /**
7 | * Jest hook which runs before each test,
8 | * @see https://jestjs.io/docs/en/api#beforeeachfn-timeout
9 | */
10 | beforeEach(() => {});
11 |
12 | it('renders without crashing', () => {
13 | /**
14 | * `asFragment`:
15 | * @see https://testing-library.com/docs/react-testing-library/api#asfragment
16 | * `baseElement`:
17 | * @see https://testing-library.com/docs/react-testing-library/api#baseelement
18 | */
19 | const {asFragment, baseElement} = render();
20 |
21 | /**
22 | * Basic snapshot test to make sure, that rendered component
23 | * matches expected footprint.
24 | */
25 | expect(asFragment()).toMatchSnapshot();
26 |
27 | /** More precise test for counter value */
28 | expect(baseElement.querySelector('strong')!.textContent).toBe('6'); // 6 is value we expect, we need to convert Number to String, because HTMLElement textContent method returns string value
29 | });
30 |
31 | it('changes counter value on button click', () => {
32 | const value = 1;
33 |
34 | /**
35 | * `getByRole`:
36 | * @see https://testing-library.com/docs/dom-testing-library/api-queries#byrole
37 | */
38 | const {getByRole, baseElement} = render();
39 |
40 | /**
41 | * Search for the button and make testing library click on it
42 | * @see https://testing-library.com/docs/react-testing-library/cheatsheet#events
43 | */
44 | fireEvent.click(getByRole('button'));
45 |
46 | /** Check if counter was incremented */
47 | expect(baseElement.querySelector('strong')!.textContent).toBe(`${value + 1}`);
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/.github/workflows/pages.yml:
--------------------------------------------------------------------------------
1 | # Simple workflow for deploying static content to GitHub Pages
2 | name: Deploy to GitHub Pages
3 |
4 | on:
5 | # Runs on pushes targeting the default branch
6 | push:
7 | branches: ["master"]
8 |
9 | # Allows you to run this workflow manually from the Actions tab
10 | workflow_dispatch:
11 |
12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13 | permissions:
14 | contents: read
15 | pages: write
16 | id-token: write
17 |
18 | # Allow one concurrent deployment
19 | concurrency:
20 | group: "pages"
21 | cancel-in-progress: true
22 |
23 | jobs:
24 | # Single deploy job since we're just deploying
25 | deploy:
26 | environment:
27 | name: github-pages
28 | url: ${{ steps.deployment.outputs.page_url }}
29 | runs-on: ubuntu-latest
30 | steps:
31 | - name: Cancel Workflow Action
32 | uses: styfle/cancel-workflow-action@0.12.1
33 | with:
34 | access_token: ${{ github.token }}
35 |
36 | - name: Checkout
37 | uses: actions/checkout@v4
38 |
39 | - name: Read .nvmrc
40 | run: echo "NVMRC=$(cat .nvmrc)" >> $GITHUB_ENV
41 | id: nvm
42 |
43 | - name: Use Node.js ${{ env.NVMRC }}
44 | uses: actions/setup-node@v4
45 | with:
46 | node-version: ${{ env.NVMRC }}
47 |
48 | - name: Install pnpm
49 | uses: pnpm/action-setup@v4
50 | with:
51 | version: 10
52 | run_install: false
53 |
54 | - name: Get pnpm store directory
55 | shell: bash
56 | run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
57 |
58 | - name: Setup pnpm cache
59 | uses: actions/cache@v4
60 | with:
61 | path: ${{ env.STORE_PATH }}
62 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
63 | restore-keys: |
64 | ${{ runner.os }}-pnpm-store-
65 |
66 | - name: Build docs
67 | run: |
68 | pnpm install
69 | pnpm run build:docs --quiet
70 |
71 | - name: Setup Pages
72 | uses: actions/configure-pages@v5
73 |
74 | - name: Upload artifact
75 | uses: actions/upload-pages-artifact@v3
76 | with:
77 | path: './storybook-static'
78 |
79 | - name: Deploy to GitHub Pages
80 | id: deployment
81 | uses: actions/deploy-pages@v4
82 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-library-template",
3 | "homepage": "https://morewings.github.io/react-library-template/",
4 | "private": false,
5 | "version": "0.1.0",
6 | "type": "module",
7 | "files": [
8 | "dist"
9 | ],
10 | "main": "./dist/index.umd.cjs",
11 | "module": "./dist/index.js",
12 | "types": "./dist/index.d.ts",
13 | "sideEffects": false,
14 | "exports": {
15 | ".": {
16 | "import": "./dist/index.js",
17 | "require": "./dist/index.umd.cjs"
18 | }
19 | },
20 | "keywords": [
21 | "react",
22 | "template",
23 | "react-testing-library",
24 | "testing-library",
25 | "eslint",
26 | "npm",
27 | "rollup",
28 | "stylelint",
29 | "library",
30 | "package",
31 | "vite",
32 | "css-modules",
33 | "typescript"
34 | ],
35 | "description": "Missing React, typescript NPM library creation template",
36 | "scripts": {
37 | "dev": "vite",
38 | "clean:lib": "rm -rf dist",
39 | "build:lib": "vite build",
40 | "build": "run-s clean:lib build:lib",
41 | "lint:code": "eslint src/** --report-unused-disable-directives",
42 | "fix:code": "run-s 'lint:code --fix'",
43 | "lint:types": "tsc --pretty --noEmit",
44 | "lint:style": "stylelint ./src/**/*.css",
45 | "fix:style": "run-s 'lint:style --fix'",
46 | "test": "jest",
47 | "preview": "vite preview",
48 | "start:docs": "storybook dev -p 6006",
49 | "build:docs": "storybook build",
50 | "generate:component": "npx generate-react-cli component",
51 | "prepare": "is-ci || husky",
52 | "lint-staged": "lint-staged"
53 | },
54 | "peerDependencies": {
55 | "react": ">=18.2.0",
56 | "react-dom": ">=18.2.0"
57 | },
58 | "dependencies": {
59 | "lodash": "^4.17.21"
60 | },
61 | "devDependencies": {
62 | "@eslint/compat": "1.3.1",
63 | "@eslint/eslintrc": "3.3.3",
64 | "@eslint/js": "9.31.0",
65 | "@storybook/addon-docs": "10.0.7",
66 | "@storybook/addon-links": "10.0.7",
67 | "@storybook/builder-vite": "10.0.7",
68 | "@storybook/react-vite": "10.0.7",
69 | "@testing-library/jest-dom": "6.6.3",
70 | "@testing-library/react": "16.3.0",
71 | "@types/jest": "30.0.0",
72 | "@types/lodash": "4.17.21",
73 | "@types/react": "19.1.8",
74 | "@types/react-dom": "19.1.6",
75 | "@typescript-eslint/eslint-plugin": "8.46.1",
76 | "@typescript-eslint/parser": "8.46.1",
77 | "@vitejs/plugin-react": "4.7.0",
78 | "@yelo/rollup-node-external": "1.0.1",
79 | "alias-kitchen": "0.2.4",
80 | "eslint": "9.31.0",
81 | "eslint-config-prettier": "10.1.8",
82 | "eslint-plugin-import": "2.32.0",
83 | "eslint-plugin-prettier": "5.5.4",
84 | "eslint-plugin-react": "7.37.5",
85 | "eslint-plugin-react-hooks": "5.2.0",
86 | "eslint-plugin-react-refresh": "0.4.24",
87 | "eslint-plugin-ssr-friendly": "1.3.0",
88 | "eslint-plugin-storybook": "10.0.7",
89 | "generate-react-cli": "8.4.9",
90 | "husky": "9.1.7",
91 | "identity-obj-proxy": "3.0.0",
92 | "is-ci": "4.1.0",
93 | "jest": "30.0.5",
94 | "jest-environment-jsdom": "30.0.5",
95 | "lint-staged": "16.1.2",
96 | "npm-run-all2": "8.0.4",
97 | "postcss": "8.5.6",
98 | "postcss-preset-env": "10.2.4",
99 | "prettier": "3.6.2",
100 | "react": "19.1.0",
101 | "react-docgen-typescript": "2.4.0",
102 | "react-dom": "19.1.0",
103 | "storybook": "10.0.7",
104 | "stylelint": "16.22.0",
105 | "stylelint-config-standard": "38.0.0",
106 | "stylelint-order": "7.0.0",
107 | "stylelint-prettier": "5.0.3",
108 | "ts-jest": "29.4.0",
109 | "ts-node": "10.9.2",
110 | "typescript": "5.8.3",
111 | "typescript-eslint": "8.46.1",
112 | "vite": "7.1.11",
113 | "vite-plugin-dts": "4.5.4"
114 | },
115 | "pnpm": {
116 | "onlyBuiltDependencies": [
117 | "esbuild",
118 | "unrs-resolver"
119 | ]
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/morewings/react-library-template/actions/workflows/merge-jobs.yml)
2 | [](https://github.com/morewings/react-library-template/actions/workflows/pages.yml)
3 | [](https://github.com/morewings/react-library-template/generate)
4 |
5 | # React Library Template
6 |
7 | [](#)
8 |
9 | This template repository is your shortcut to building awesome React components and libraries!
10 |
11 | Forget about the tedious setup – we've got you covered. Focus on writing your code, and let this template handle the rest.
12 |
13 | ## Features
14 |
15 | - **TypeScript & JavaScript**: Write your code in the language you prefer.
16 | - **Blazing fast**: **pnpm** for speedy package management and **Vite** for lightning-fast builds.
17 | - **Husky** enforces pre-commit hooks, **Eslint** and **Stylelint** will keep your code tidy and consistent.
18 | - **Jest** and **react-testing-library** help you write robust tests.
19 | - **Storybook** lets you create interactive demos and docs for your components.
20 | - **Optional Tailwind CSS**: If you're into it, you can easily enable Tailwind CSS for styling.
21 |
22 | See it in action: [Demo Storybook](https://morewings.github.io/react-library-template/)
23 |
24 | This template is your starting point for building high-quality React libraries. Clone it, customize it, and let's build something amazing!
25 |
26 | ## Quickstart
27 |
28 | ### Prerequisites
29 |
30 | 1. Install **Node** >= 20.x.
31 | 2. Install **pnpm**. E.g. `corepack prepare pnpm@latest --activate`.
32 |
33 |
34 | ### Installation
35 |
36 | Manually clone repo or use `degit`.
37 |
38 | ```shell script
39 | # With CSS Modules config
40 | npx degit github:morewings/react-library-template my-library
41 | # With Tailwind CSS config
42 | npx degit github:morewings/react-library-template#tailwind my-library
43 | cd ./my-library
44 | pnpm i
45 | ```
46 |
47 |
48 | ## Enable Tailwind CSS
49 |
50 | You can find all changes at this [PR](https://github.com/morewings/react-library-template/pull/161) and [tailwind](https://github.com/morewings/react-library-template/tree/tailwind) branch.
51 |
52 | ## Improve tree shaking
53 |
54 | The default settings allow modern bundlers such as Vite and esbuild successfully tree-shake unused modules from the bundle.
55 | Unfortunately there are problems with Next.js and Webpack not capable to tree-shake single file ES Module.
56 |
57 | In order to fix this enable `preserveModules` setting in Rollup options.
58 |
59 | ```ts
60 | import {defineConfig} from 'vite';
61 |
62 | export default defineConfig(() => ({
63 | // ...
64 | build: {
65 | lib: {
66 | // ...
67 | fileName: (format, entryName) => {
68 | // Create entry file(s) inside the bundle
69 | if (entryName === 'src/lib/index') {
70 | return `index.${format === 'es' ? 'js' : 'cjs'}`;
71 | // Organize external dependencies which included in the bundle
72 | } else if (entryName.includes('node_modules')) {
73 | return `external/module.${format === 'es' ? 'js' : 'cjs'}`
74 | }
75 | // Keep other modules in places
76 | return `${entryName}.${format === 'es' ? 'js' : 'cjs'}`;
77 | },
78 | // Change bundle formats to ES Modules and commonJS.
79 | // UMD bundle will not work with preserveModules:true
80 | formats: ['es', 'cjs'],
81 | },
82 | rollupOptions: {
83 | // ...
84 | output: {
85 | // ...
86 | preserveModules: true,
87 | },
88 | },
89 | },
90 | }));
91 |
92 | ```
93 |
94 | You can find all changes at corresponding [PR](https://github.com/morewings/react-library-template/pull/352) and [tree-shaking](https://github.com/morewings/react-library-template/tree/tree-shaking) branch.
95 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 |
3 | import eslint from '@eslint/js';
4 | import eslintTS from 'typescript-eslint';
5 | import tsParser from '@typescript-eslint/parser';
6 | import pluginImport from 'eslint-plugin-import';
7 | import pluginSSRFriendly from 'eslint-plugin-ssr-friendly';
8 | import pluginPrettier from 'eslint-plugin-prettier';
9 | import pluginTypescript from '@typescript-eslint/eslint-plugin';
10 | import pluginReactRefresh from 'eslint-plugin-react-refresh';
11 | import configReactRecommended from 'eslint-plugin-react/configs/recommended.js';
12 | import configReactJSXRuntime from 'eslint-plugin-react/configs/jsx-runtime.js';
13 | import pluginReactHooks from 'eslint-plugin-react-hooks';
14 | import {fixupPluginRules} from '@eslint/compat';
15 | import configPrettierRecommended from 'eslint-plugin-prettier/recommended';
16 |
17 | export default [
18 | eslint.configs.recommended,
19 | ...eslintTS.configs.recommended,
20 | ...eslintTS.configs.stylistic,
21 | configReactRecommended,
22 | configReactJSXRuntime,
23 | configPrettierRecommended,
24 | {
25 | files: ['**/*.{js,ts,tsx,cjs}'],
26 | linterOptions: {
27 | reportUnusedDisableDirectives: 'error',
28 | },
29 | languageOptions: {
30 | parser: tsParser,
31 | parserOptions: {
32 | ecmaFeatures: {modules: true},
33 | ecmaVersion: 'latest',
34 | project: './tsconfig.linter.json',
35 | },
36 | },
37 | settings: {
38 | react: {
39 | version: 'detect',
40 | },
41 | },
42 | plugins: {
43 | import: pluginImport,
44 | prettier: pluginPrettier,
45 | '@typescript-eslint': pluginTypescript,
46 | 'react-refresh': pluginReactRefresh,
47 | 'react-hooks': fixupPluginRules(pluginReactHooks),
48 | 'ssr-friendly': fixupPluginRules(pluginSSRFriendly),
49 | },
50 | rules: {
51 | ...pluginReactHooks.configs.recommended.rules,
52 | ...pluginSSRFriendly.configs.recommended.rules,
53 | /**
54 | * Allow empty arrow functions `() => {}`, while keeping other empty functions restricted
55 | * @see https://eslint.org/docs/latest/rules/no-empty-function#allow-arrowfunctions
56 | */
57 | '@typescript-eslint/no-empty-function': ['error', {allow: ['arrowFunctions']}],
58 | '@typescript-eslint/ban-ts-comment': 1,
59 | 'no-const-assign': 'error',
60 | /** Restrict imports from devDependencies since they are not included in library build. peerDependencies are ok */
61 | 'import/no-extraneous-dependencies': [
62 | 'error',
63 | {
64 | devDependencies: false,
65 | peerDependencies: true,
66 | },
67 | ],
68 | /**
69 | * Enforce import order with empty lines between import group
70 | * @see https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md
71 | */
72 | 'import/order': [
73 | 'error',
74 | {
75 | groups: ['builtin', 'external', 'internal', ['parent', 'sibling', 'index']],
76 | pathGroups: [
77 | {
78 | pattern: '@/**',
79 | group: 'internal',
80 | },
81 | ],
82 | 'newlines-between': 'always',
83 | },
84 | ],
85 | /**
86 | * Disallow combined module and type imports like this `import React, {FC} from 'react'`.
87 | * Eslint will try to split into type and module imports instead
88 | * @see https://typescript-eslint.io/rules/consistent-type-imports/
89 | */
90 | '@typescript-eslint/consistent-type-imports': 'error',
91 | 'import/no-cycle': 'error',
92 | 'prettier/prettier': [
93 | 'error',
94 | {
95 | semi: true,
96 | singleQuote: true,
97 | jsxSingleQuote: false,
98 | trailingComma: 'es5',
99 | bracketSpacing: false,
100 | jsxBracketSameLine: true,
101 | arrowParens: 'avoid',
102 | },
103 | ],
104 | /* Required by vite */
105 | 'react-refresh/only-export-components': ['warn', {allowConstantExport: true}],
106 | '@typescript-eslint/consistent-type-definitions': ['error', 'type'],
107 | /**
108 | * Allow unused variables with names stating with '_'
109 | * @see https://eslint.org/docs/latest/rules/no-unused-vars
110 | * @see https://typescript-eslint.io/rules/no-unused-vars/
111 | */
112 | '@typescript-eslint/no-unused-vars': [
113 | 'error',
114 | {
115 | argsIgnorePattern: '^_',
116 | varsIgnorePattern: '^_',
117 | caughtErrorsIgnorePattern: '^_',
118 | ignoreRestSiblings: true,
119 | args: 'after-used',
120 | },
121 | ],
122 | },
123 | },
124 | /* Allow devDependencies imports for tests and config files */
125 | {
126 | files: [
127 | '**/*.spec.*',
128 | '**/testUtils/*.{js,jsx,ts,tsx}',
129 | '*/*.{js,jsx,ts,tsx}',
130 | '**/setupTests.ts',
131 | '**/*.stories.*',
132 | '*.config.{js,ts}',
133 | ],
134 | plugins: {
135 | import: pluginImport,
136 | },
137 | rules: {
138 | 'import/no-extraneous-dependencies': [
139 | 'error',
140 | {
141 | devDependencies: true,
142 | peerDependencies: true,
143 | },
144 | ],
145 | },
146 | },
147 | /* Disable `environment` directory imports for library files */
148 | {
149 | files: ['src/lib/**/*.{js,jsx,ts,tsx}'],
150 | rules: {
151 | 'no-restricted-imports': [
152 | 'error',
153 | {
154 | patterns: [
155 | {
156 | group: ['**/environment/**'],
157 | message: 'Imports from environment directory are forbidden in the library files.',
158 | },
159 | ],
160 | },
161 | ],
162 | },
163 | },
164 | /* Disable `template` directory imports for all files */
165 | {
166 | files: ['src/**/*.{js,jsx,ts,tsx}'],
167 | rules: {
168 | 'no-restricted-imports': [
169 | 'error',
170 | {
171 | patterns: [
172 | {
173 | group: ['**/templates/**'],
174 | message: 'Imports from templates directory are forbidden.',
175 | },
176 | ],
177 | },
178 | ],
179 | },
180 | },
181 | /**
182 | * Disable rules of hooks for story files in order to have better story code display.
183 | * @see TemplateName.stories.tsx
184 | */
185 | {
186 | files: ['**/*.stories.*'],
187 | rules: {
188 | 'react-hooks/rules-of-hooks': 'off',
189 | },
190 | },
191 | {
192 | ignores: ['**/*.snap'],
193 | },
194 | ];
195 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | charset = utf-8
3 | end_of_line = lf
4 | indent_size = 4
5 | indent_style = space
6 | insert_final_newline = true
7 | max_line_length = 120
8 | tab_width = 4
9 | trim_trailing_whitespace = true
10 | ij_continuation_indent_size = 8
11 | ij_formatter_off_tag = @formatter:off
12 | ij_formatter_on_tag = @formatter:on
13 | ij_formatter_tags_enabled = true
14 | ij_smart_tabs = false
15 | ij_visual_guides =
16 | ij_wrap_on_typing = false
17 |
18 | [*.css]
19 | ij_css_align_closing_brace_with_properties = false
20 | ij_css_blank_lines_around_nested_selector = 1
21 | ij_css_blank_lines_between_blocks = 1
22 | ij_css_block_comment_add_space = false
23 | ij_css_brace_placement = end_of_line
24 | ij_css_enforce_quotes_on_format = false
25 | ij_css_hex_color_long_format = false
26 | ij_css_hex_color_lower_case = false
27 | ij_css_hex_color_short_format = false
28 | ij_css_hex_color_upper_case = false
29 | ij_css_keep_blank_lines_in_code = 2
30 | ij_css_keep_indents_on_empty_lines = false
31 | ij_css_keep_single_line_blocks = false
32 | ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
33 | ij_css_space_after_colon = true
34 | ij_css_space_before_opening_brace = true
35 | ij_css_use_double_quotes = true
36 | ij_css_value_alignment = do_not_align
37 |
38 | [*.feature]
39 | indent_size = 2
40 | ij_gherkin_keep_indents_on_empty_lines = false
41 |
42 | [*.less]
43 | ij_less_align_closing_brace_with_properties = false
44 | ij_less_blank_lines_around_nested_selector = 1
45 | ij_less_blank_lines_between_blocks = 1
46 | ij_less_block_comment_add_space = false
47 | ij_less_brace_placement = 0
48 | ij_less_enforce_quotes_on_format = false
49 | ij_less_hex_color_long_format = false
50 | ij_less_hex_color_lower_case = false
51 | ij_less_hex_color_short_format = false
52 | ij_less_hex_color_upper_case = false
53 | ij_less_keep_blank_lines_in_code = 2
54 | ij_less_keep_indents_on_empty_lines = false
55 | ij_less_keep_single_line_blocks = false
56 | ij_less_line_comment_add_space = false
57 | ij_less_line_comment_at_first_column = false
58 | ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
59 | ij_less_space_after_colon = true
60 | ij_less_space_before_opening_brace = true
61 | ij_less_use_double_quotes = true
62 | ij_less_value_alignment = 0
63 |
64 | [*.sass]
65 | ij_sass_align_closing_brace_with_properties = false
66 | ij_sass_blank_lines_around_nested_selector = 1
67 | ij_sass_blank_lines_between_blocks = 1
68 | ij_sass_brace_placement = 0
69 | ij_sass_enforce_quotes_on_format = false
70 | ij_sass_hex_color_long_format = false
71 | ij_sass_hex_color_lower_case = false
72 | ij_sass_hex_color_short_format = false
73 | ij_sass_hex_color_upper_case = false
74 | ij_sass_keep_blank_lines_in_code = 2
75 | ij_sass_keep_indents_on_empty_lines = false
76 | ij_sass_keep_single_line_blocks = false
77 | ij_sass_line_comment_add_space = false
78 | ij_sass_line_comment_at_first_column = false
79 | ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
80 | ij_sass_space_after_colon = true
81 | ij_sass_space_before_opening_brace = true
82 | ij_sass_use_double_quotes = true
83 | ij_sass_value_alignment = 0
84 |
85 | [*.scss]
86 | ij_scss_align_closing_brace_with_properties = false
87 | ij_scss_blank_lines_around_nested_selector = 1
88 | ij_scss_blank_lines_between_blocks = 1
89 | ij_scss_block_comment_add_space = false
90 | ij_scss_brace_placement = 0
91 | ij_scss_enforce_quotes_on_format = false
92 | ij_scss_hex_color_long_format = false
93 | ij_scss_hex_color_lower_case = false
94 | ij_scss_hex_color_short_format = false
95 | ij_scss_hex_color_upper_case = false
96 | ij_scss_keep_blank_lines_in_code = 2
97 | ij_scss_keep_indents_on_empty_lines = false
98 | ij_scss_keep_single_line_blocks = false
99 | ij_scss_line_comment_add_space = false
100 | ij_scss_line_comment_at_first_column = false
101 | ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
102 | ij_scss_space_after_colon = true
103 | ij_scss_space_before_opening_brace = true
104 | ij_scss_use_double_quotes = true
105 | ij_scss_value_alignment = 0
106 |
107 | [*.vue]
108 | indent_size = 2
109 | tab_width = 2
110 | ij_continuation_indent_size = 2
111 | ij_visual_guides = 80
112 | ij_vue_indent_children_of_top_level = template
113 | ij_vue_interpolation_new_line_after_start_delimiter = false
114 | ij_vue_interpolation_new_line_before_end_delimiter = false
115 | ij_vue_interpolation_wrap = off
116 | ij_vue_keep_indents_on_empty_lines = false
117 | ij_vue_spaces_within_interpolation_expressions = true
118 |
119 | [.editorconfig]
120 | ij_editorconfig_align_group_field_declarations = false
121 | ij_editorconfig_space_after_colon = false
122 | ij_editorconfig_space_after_comma = true
123 | ij_editorconfig_space_before_colon = false
124 | ij_editorconfig_space_before_comma = false
125 | ij_editorconfig_spaces_around_assignment_operators = true
126 |
127 | [{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}]
128 | ij_xml_align_attributes = true
129 | ij_xml_align_text = false
130 | ij_xml_attribute_wrap = normal
131 | ij_xml_block_comment_add_space = false
132 | ij_xml_block_comment_at_first_column = true
133 | ij_xml_keep_blank_lines = 2
134 | ij_xml_keep_indents_on_empty_lines = false
135 | ij_xml_keep_line_breaks = true
136 | ij_xml_keep_line_breaks_in_text = true
137 | ij_xml_keep_whitespaces = false
138 | ij_xml_keep_whitespaces_around_cdata = preserve
139 | ij_xml_keep_whitespaces_inside_cdata = false
140 | ij_xml_line_comment_at_first_column = true
141 | ij_xml_space_after_tag_name = false
142 | ij_xml_space_around_equals_in_attribute = false
143 | ij_xml_space_inside_empty_tag = false
144 | ij_xml_text_wrap = normal
145 |
146 | [{*.ats,*.cts,*.mts,*.ts,*tsx}]
147 | ij_continuation_indent_size = 4
148 | ij_visual_guides = 80
149 | ij_typescript_align_imports = false
150 | ij_typescript_align_multiline_array_initializer_expression = false
151 | ij_typescript_align_multiline_binary_operation = false
152 | ij_typescript_align_multiline_chained_methods = false
153 | ij_typescript_align_multiline_extends_list = false
154 | ij_typescript_align_multiline_for = true
155 | ij_typescript_align_multiline_parameters = true
156 | ij_typescript_align_multiline_parameters_in_calls = false
157 | ij_typescript_align_multiline_ternary_operation = false
158 | ij_typescript_align_object_properties = 0
159 | ij_typescript_align_union_types = false
160 | ij_typescript_align_var_statements = 0
161 | ij_typescript_array_initializer_new_line_after_left_brace = false
162 | ij_typescript_array_initializer_right_brace_on_new_line = false
163 | ij_typescript_array_initializer_wrap = off
164 | ij_typescript_assignment_wrap = off
165 | ij_typescript_binary_operation_sign_on_next_line = false
166 | ij_typescript_binary_operation_wrap = off
167 | ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
168 | ij_typescript_blank_lines_after_imports = 1
169 | ij_typescript_blank_lines_around_class = 1
170 | ij_typescript_blank_lines_around_field = 0
171 | ij_typescript_blank_lines_around_field_in_interface = 0
172 | ij_typescript_blank_lines_around_function = 1
173 | ij_typescript_blank_lines_around_method = 1
174 | ij_typescript_blank_lines_around_method_in_interface = 1
175 | ij_typescript_block_brace_style = end_of_line
176 | ij_typescript_block_comment_add_space = false
177 | ij_typescript_block_comment_at_first_column = true
178 | ij_typescript_call_parameters_new_line_after_left_paren = false
179 | ij_typescript_call_parameters_right_paren_on_new_line = false
180 | ij_typescript_call_parameters_wrap = off
181 | ij_typescript_catch_on_new_line = false
182 | ij_typescript_chained_call_dot_on_new_line = true
183 | ij_typescript_class_brace_style = end_of_line
184 | ij_typescript_comma_on_new_line = false
185 | ij_typescript_do_while_brace_force = never
186 | ij_typescript_else_on_new_line = false
187 | ij_typescript_enforce_trailing_comma = whenmultiline
188 | ij_typescript_enum_constants_wrap = on_every_item
189 | ij_typescript_extends_keyword_wrap = off
190 | ij_typescript_extends_list_wrap = off
191 | ij_typescript_field_prefix = _
192 | ij_typescript_file_name_style = relaxed
193 | ij_typescript_finally_on_new_line = false
194 | ij_typescript_for_brace_force = never
195 | ij_typescript_for_statement_new_line_after_left_paren = false
196 | ij_typescript_for_statement_right_paren_on_new_line = false
197 | ij_typescript_for_statement_wrap = off
198 | ij_typescript_force_quote_style = true
199 | ij_typescript_force_semicolon_style = true
200 | ij_typescript_function_expression_brace_style = end_of_line
201 | ij_typescript_if_brace_force = never
202 | ij_typescript_import_merge_members = global
203 | ij_typescript_import_prefer_absolute_path = global
204 | ij_typescript_import_sort_members = true
205 | ij_typescript_import_sort_module_name = false
206 | ij_typescript_import_use_node_resolution = true
207 | ij_typescript_imports_wrap = on_every_item
208 | ij_typescript_indent_case_from_switch = true
209 | ij_typescript_indent_chained_calls = true
210 | ij_typescript_indent_package_children = 0
211 | ij_typescript_jsdoc_include_types = false
212 | ij_typescript_jsx_attribute_value = braces
213 | ij_typescript_keep_blank_lines_in_code = 2
214 | ij_typescript_keep_first_column_comment = true
215 | ij_typescript_keep_indents_on_empty_lines = false
216 | ij_typescript_keep_line_breaks = true
217 | ij_typescript_keep_simple_blocks_in_one_line = false
218 | ij_typescript_keep_simple_methods_in_one_line = false
219 | ij_typescript_line_comment_add_space = true
220 | ij_typescript_line_comment_at_first_column = false
221 | ij_typescript_method_brace_style = end_of_line
222 | ij_typescript_method_call_chain_wrap = off
223 | ij_typescript_method_parameters_new_line_after_left_paren = false
224 | ij_typescript_method_parameters_right_paren_on_new_line = false
225 | ij_typescript_method_parameters_wrap = off
226 | ij_typescript_object_literal_wrap = on_every_item
227 | ij_typescript_object_types_wrap = on_every_item
228 | ij_typescript_parentheses_expression_new_line_after_left_paren = false
229 | ij_typescript_parentheses_expression_right_paren_on_new_line = false
230 | ij_typescript_place_assignment_sign_on_next_line = false
231 | ij_typescript_prefer_as_type_cast = false
232 | ij_typescript_prefer_explicit_types_function_expression_returns = false
233 | ij_typescript_prefer_explicit_types_function_returns = false
234 | ij_typescript_prefer_explicit_types_vars_fields = false
235 | ij_typescript_prefer_parameters_wrap = false
236 | ij_typescript_property_prefix =
237 | ij_typescript_reformat_c_style_comments = false
238 | ij_typescript_space_after_colon = true
239 | ij_typescript_space_after_comma = true
240 | ij_typescript_space_after_dots_in_rest_parameter = false
241 | ij_typescript_space_after_generator_mult = true
242 | ij_typescript_space_after_property_colon = true
243 | ij_typescript_space_after_quest = true
244 | ij_typescript_space_after_type_colon = true
245 | ij_typescript_space_after_unary_not = false
246 | ij_typescript_space_before_async_arrow_lparen = true
247 | ij_typescript_space_before_catch_keyword = true
248 | ij_typescript_space_before_catch_left_brace = true
249 | ij_typescript_space_before_catch_parentheses = true
250 | ij_typescript_space_before_class_lbrace = true
251 | ij_typescript_space_before_class_left_brace = true
252 | ij_typescript_space_before_colon = true
253 | ij_typescript_space_before_comma = false
254 | ij_typescript_space_before_do_left_brace = true
255 | ij_typescript_space_before_else_keyword = true
256 | ij_typescript_space_before_else_left_brace = true
257 | ij_typescript_space_before_finally_keyword = true
258 | ij_typescript_space_before_finally_left_brace = true
259 | ij_typescript_space_before_for_left_brace = true
260 | ij_typescript_space_before_for_parentheses = true
261 | ij_typescript_space_before_for_semicolon = false
262 | ij_typescript_space_before_function_left_parenth = false
263 | ij_typescript_space_before_generator_mult = false
264 | ij_typescript_space_before_if_left_brace = true
265 | ij_typescript_space_before_if_parentheses = true
266 | ij_typescript_space_before_method_call_parentheses = false
267 | ij_typescript_space_before_method_left_brace = true
268 | ij_typescript_space_before_method_parentheses = false
269 | ij_typescript_space_before_property_colon = false
270 | ij_typescript_space_before_quest = true
271 | ij_typescript_space_before_switch_left_brace = true
272 | ij_typescript_space_before_switch_parentheses = true
273 | ij_typescript_space_before_try_left_brace = true
274 | ij_typescript_space_before_type_colon = false
275 | ij_typescript_space_before_unary_not = false
276 | ij_typescript_space_before_while_keyword = true
277 | ij_typescript_space_before_while_left_brace = true
278 | ij_typescript_space_before_while_parentheses = true
279 | ij_typescript_spaces_around_additive_operators = true
280 | ij_typescript_spaces_around_arrow_function_operator = true
281 | ij_typescript_spaces_around_assignment_operators = true
282 | ij_typescript_spaces_around_bitwise_operators = true
283 | ij_typescript_spaces_around_equality_operators = true
284 | ij_typescript_spaces_around_logical_operators = true
285 | ij_typescript_spaces_around_multiplicative_operators = true
286 | ij_typescript_spaces_around_relational_operators = true
287 | ij_typescript_spaces_around_shift_operators = true
288 | ij_typescript_spaces_around_unary_operator = false
289 | ij_typescript_spaces_within_array_initializer_brackets = false
290 | ij_typescript_spaces_within_brackets = false
291 | ij_typescript_spaces_within_catch_parentheses = false
292 | ij_typescript_spaces_within_for_parentheses = false
293 | ij_typescript_spaces_within_if_parentheses = false
294 | ij_typescript_spaces_within_imports = false
295 | ij_typescript_spaces_within_interpolation_expressions = false
296 | ij_typescript_spaces_within_method_call_parentheses = false
297 | ij_typescript_spaces_within_method_parentheses = false
298 | ij_typescript_spaces_within_object_literal_braces = false
299 | ij_typescript_spaces_within_object_type_braces = false
300 | ij_typescript_spaces_within_parentheses = false
301 | ij_typescript_spaces_within_switch_parentheses = false
302 | ij_typescript_spaces_within_type_assertion = false
303 | ij_typescript_spaces_within_union_types = true
304 | ij_typescript_spaces_within_while_parentheses = false
305 | ij_typescript_special_else_if_treatment = true
306 | ij_typescript_ternary_operation_signs_on_next_line = false
307 | ij_typescript_ternary_operation_wrap = off
308 | ij_typescript_union_types_wrap = on_every_item
309 | ij_typescript_use_chained_calls_group_indents = false
310 | ij_typescript_use_double_quotes = false
311 | ij_typescript_use_explicit_js_extension = auto
312 | ij_typescript_use_path_mapping = always
313 | ij_typescript_use_public_modifier = false
314 | ij_typescript_use_semicolon_after_statement = true
315 | ij_typescript_var_declaration_wrap = normal
316 | ij_typescript_while_brace_force = never
317 | ij_typescript_while_on_new_line = false
318 | ij_typescript_wrap_comments = false
319 |
320 | [{*.bash,*.sh,*.zsh}]
321 | indent_size = 2
322 | tab_width = 2
323 | ij_shell_binary_ops_start_line = false
324 | ij_shell_keep_column_alignment_padding = false
325 | ij_shell_minify_program = false
326 | ij_shell_redirect_followed_by_space = false
327 | ij_shell_switch_cases_indented = false
328 | ij_shell_use_unix_line_separator = true
329 |
330 | [{*.cjs,*.js,*.js }]
331 | indent_size = 4
332 | tab_width = 4
333 | ij_continuation_indent_size = 4
334 | ij_visual_guides = 80
335 | ij_javascript_align_imports = false
336 | ij_javascript_align_multiline_array_initializer_expression = false
337 | ij_javascript_align_multiline_binary_operation = false
338 | ij_javascript_align_multiline_chained_methods = false
339 | ij_javascript_align_multiline_extends_list = false
340 | ij_javascript_align_multiline_for = true
341 | ij_javascript_align_multiline_parameters = true
342 | ij_javascript_align_multiline_parameters_in_calls = false
343 | ij_javascript_align_multiline_ternary_operation = false
344 | ij_javascript_align_object_properties = 0
345 | ij_javascript_align_union_types = false
346 | ij_javascript_align_var_statements = 0
347 | ij_javascript_array_initializer_new_line_after_left_brace = false
348 | ij_javascript_array_initializer_right_brace_on_new_line = false
349 | ij_javascript_array_initializer_wrap = off
350 | ij_javascript_assignment_wrap = off
351 | ij_javascript_binary_operation_sign_on_next_line = false
352 | ij_javascript_binary_operation_wrap = off
353 | ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
354 | ij_javascript_blank_lines_after_imports = 1
355 | ij_javascript_blank_lines_around_class = 1
356 | ij_javascript_blank_lines_around_field = 0
357 | ij_javascript_blank_lines_around_function = 1
358 | ij_javascript_blank_lines_around_method = 1
359 | ij_javascript_block_brace_style = end_of_line
360 | ij_javascript_block_comment_add_space = false
361 | ij_javascript_block_comment_at_first_column = true
362 | ij_javascript_call_parameters_new_line_after_left_paren = false
363 | ij_javascript_call_parameters_right_paren_on_new_line = false
364 | ij_javascript_call_parameters_wrap = off
365 | ij_javascript_catch_on_new_line = false
366 | ij_javascript_chained_call_dot_on_new_line = true
367 | ij_javascript_class_brace_style = end_of_line
368 | ij_javascript_comma_on_new_line = false
369 | ij_javascript_do_while_brace_force = never
370 | ij_javascript_else_on_new_line = false
371 | ij_javascript_enforce_trailing_comma = whenmultiline
372 | ij_javascript_extends_keyword_wrap = off
373 | ij_javascript_extends_list_wrap = off
374 | ij_javascript_field_prefix = _
375 | ij_javascript_file_name_style = relaxed
376 | ij_javascript_finally_on_new_line = false
377 | ij_javascript_for_brace_force = never
378 | ij_javascript_for_statement_new_line_after_left_paren = false
379 | ij_javascript_for_statement_right_paren_on_new_line = false
380 | ij_javascript_for_statement_wrap = off
381 | ij_javascript_force_quote_style = true
382 | ij_javascript_force_semicolon_style = true
383 | ij_javascript_function_expression_brace_style = end_of_line
384 | ij_javascript_if_brace_force = never
385 | ij_javascript_import_merge_members = global
386 | ij_javascript_import_prefer_absolute_path = true
387 | ij_javascript_import_sort_members = true
388 | ij_javascript_import_sort_module_name = false
389 | ij_javascript_import_use_node_resolution = true
390 | ij_javascript_imports_wrap = on_every_item
391 | ij_javascript_indent_case_from_switch = true
392 | ij_javascript_indent_chained_calls = true
393 | ij_javascript_indent_package_children = 0
394 | ij_javascript_jsx_attribute_value = braces
395 | ij_javascript_keep_blank_lines_in_code = 2
396 | ij_javascript_keep_first_column_comment = true
397 | ij_javascript_keep_indents_on_empty_lines = false
398 | ij_javascript_keep_line_breaks = true
399 | ij_javascript_keep_simple_blocks_in_one_line = false
400 | ij_javascript_keep_simple_methods_in_one_line = false
401 | ij_javascript_line_comment_add_space = true
402 | ij_javascript_line_comment_at_first_column = false
403 | ij_javascript_method_brace_style = end_of_line
404 | ij_javascript_method_call_chain_wrap = off
405 | ij_javascript_method_parameters_new_line_after_left_paren = false
406 | ij_javascript_method_parameters_right_paren_on_new_line = false
407 | ij_javascript_method_parameters_wrap = off
408 | ij_javascript_object_literal_wrap = on_every_item
409 | ij_javascript_object_types_wrap = on_every_item
410 | ij_javascript_parentheses_expression_new_line_after_left_paren = false
411 | ij_javascript_parentheses_expression_right_paren_on_new_line = false
412 | ij_javascript_place_assignment_sign_on_next_line = false
413 | ij_javascript_prefer_as_type_cast = false
414 | ij_javascript_prefer_explicit_types_function_expression_returns = false
415 | ij_javascript_prefer_explicit_types_function_returns = false
416 | ij_javascript_prefer_explicit_types_vars_fields = false
417 | ij_javascript_prefer_parameters_wrap = false
418 | ij_javascript_property_prefix =
419 | ij_javascript_reformat_c_style_comments = false
420 | ij_javascript_space_after_colon = true
421 | ij_javascript_space_after_comma = true
422 | ij_javascript_space_after_dots_in_rest_parameter = false
423 | ij_javascript_space_after_generator_mult = true
424 | ij_javascript_space_after_property_colon = true
425 | ij_javascript_space_after_quest = true
426 | ij_javascript_space_after_type_colon = true
427 | ij_javascript_space_after_unary_not = false
428 | ij_javascript_space_before_async_arrow_lparen = true
429 | ij_javascript_space_before_catch_keyword = true
430 | ij_javascript_space_before_catch_left_brace = true
431 | ij_javascript_space_before_catch_parentheses = true
432 | ij_javascript_space_before_class_lbrace = true
433 | ij_javascript_space_before_class_left_brace = true
434 | ij_javascript_space_before_colon = true
435 | ij_javascript_space_before_comma = false
436 | ij_javascript_space_before_do_left_brace = true
437 | ij_javascript_space_before_else_keyword = true
438 | ij_javascript_space_before_else_left_brace = true
439 | ij_javascript_space_before_finally_keyword = true
440 | ij_javascript_space_before_finally_left_brace = true
441 | ij_javascript_space_before_for_left_brace = true
442 | ij_javascript_space_before_for_parentheses = true
443 | ij_javascript_space_before_for_semicolon = false
444 | ij_javascript_space_before_function_left_parenth = false
445 | ij_javascript_space_before_generator_mult = false
446 | ij_javascript_space_before_if_left_brace = true
447 | ij_javascript_space_before_if_parentheses = true
448 | ij_javascript_space_before_method_call_parentheses = false
449 | ij_javascript_space_before_method_left_brace = true
450 | ij_javascript_space_before_method_parentheses = false
451 | ij_javascript_space_before_property_colon = false
452 | ij_javascript_space_before_quest = true
453 | ij_javascript_space_before_switch_left_brace = true
454 | ij_javascript_space_before_switch_parentheses = true
455 | ij_javascript_space_before_try_left_brace = true
456 | ij_javascript_space_before_type_colon = false
457 | ij_javascript_space_before_unary_not = false
458 | ij_javascript_space_before_while_keyword = true
459 | ij_javascript_space_before_while_left_brace = true
460 | ij_javascript_space_before_while_parentheses = true
461 | ij_javascript_spaces_around_additive_operators = true
462 | ij_javascript_spaces_around_arrow_function_operator = true
463 | ij_javascript_spaces_around_assignment_operators = true
464 | ij_javascript_spaces_around_bitwise_operators = true
465 | ij_javascript_spaces_around_equality_operators = true
466 | ij_javascript_spaces_around_logical_operators = true
467 | ij_javascript_spaces_around_multiplicative_operators = true
468 | ij_javascript_spaces_around_relational_operators = true
469 | ij_javascript_spaces_around_shift_operators = true
470 | ij_javascript_spaces_around_unary_operator = false
471 | ij_javascript_spaces_within_array_initializer_brackets = false
472 | ij_javascript_spaces_within_brackets = false
473 | ij_javascript_spaces_within_catch_parentheses = false
474 | ij_javascript_spaces_within_for_parentheses = false
475 | ij_javascript_spaces_within_if_parentheses = false
476 | ij_javascript_spaces_within_imports = false
477 | ij_javascript_spaces_within_interpolation_expressions = false
478 | ij_javascript_spaces_within_method_call_parentheses = false
479 | ij_javascript_spaces_within_method_parentheses = false
480 | ij_javascript_spaces_within_object_literal_braces = false
481 | ij_javascript_spaces_within_object_type_braces = false
482 | ij_javascript_spaces_within_parentheses = false
483 | ij_javascript_spaces_within_switch_parentheses = false
484 | ij_javascript_spaces_within_type_assertion = false
485 | ij_javascript_spaces_within_union_types = true
486 | ij_javascript_spaces_within_while_parentheses = false
487 | ij_javascript_special_else_if_treatment = true
488 | ij_javascript_ternary_operation_signs_on_next_line = false
489 | ij_javascript_ternary_operation_wrap = off
490 | ij_javascript_union_types_wrap = on_every_item
491 | ij_javascript_use_chained_calls_group_indents = false
492 | ij_javascript_use_double_quotes = false
493 | ij_javascript_use_explicit_js_extension = auto
494 | ij_javascript_use_path_mapping = always
495 | ij_javascript_use_public_modifier = false
496 | ij_javascript_use_semicolon_after_statement = true
497 | ij_javascript_var_declaration_wrap = normal
498 | ij_javascript_while_brace_force = never
499 | ij_javascript_while_on_new_line = false
500 | ij_javascript_wrap_comments = false
501 |
502 | [{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.babelrc.dist,.eslintrc,.lintstagedrc,.mdx.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}]
503 | indent_size = 2
504 | ij_json_array_wrapping = split_into_lines
505 | ij_json_keep_blank_lines_in_code = 0
506 | ij_json_keep_indents_on_empty_lines = false
507 | ij_json_keep_line_breaks = true
508 | ij_json_keep_trailing_comma = false
509 | ij_json_object_wrapping = split_into_lines
510 | ij_json_property_alignment = do_not_align
511 | ij_json_space_after_colon = true
512 | ij_json_space_after_comma = true
513 | ij_json_space_before_colon = false
514 | ij_json_space_before_comma = false
515 | ij_json_spaces_within_braces = false
516 | ij_json_spaces_within_brackets = false
517 | ij_json_wrap_long_lines = false
518 |
519 | [{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
520 | indent_size = 2
521 | tab_width = 2
522 | ij_continuation_indent_size = 2
523 | ij_visual_guides = 80
524 | ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
525 | ij_html_align_attributes = true
526 | ij_html_align_text = false
527 | ij_html_attribute_wrap = normal
528 | ij_html_block_comment_add_space = false
529 | ij_html_block_comment_at_first_column = true
530 | ij_html_do_not_align_children_of_min_lines = 0
531 | ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
532 | ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot
533 | ij_html_enforce_quotes = true
534 | ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
535 | ij_html_keep_blank_lines = 2
536 | ij_html_keep_indents_on_empty_lines = false
537 | ij_html_keep_line_breaks = true
538 | ij_html_keep_line_breaks_in_text = true
539 | ij_html_keep_whitespaces = false
540 | ij_html_keep_whitespaces_inside = span,pre,textarea
541 | ij_html_line_comment_at_first_column = true
542 | ij_html_new_line_after_last_attribute = never
543 | ij_html_new_line_before_first_attribute = never
544 | ij_html_quote_style = single
545 | ij_html_remove_new_line_before_tags = br
546 | ij_html_space_after_tag_name = false
547 | ij_html_space_around_equality_in_attribute = false
548 | ij_html_space_inside_empty_tag = true
549 | ij_html_text_wrap = normal
550 |
551 | [{*.http,*.rest}]
552 | indent_size = 0
553 | ij_continuation_indent_size = 4
554 | ij_http-request_call_parameters_wrap = normal
555 | ij_http-request_method_parameters_wrap = split_into_lines
556 | ij_http-request_space_before_comma = true
557 | ij_http-request_spaces_around_assignment_operators = true
558 |
559 | [{*.markdown,*.md}]
560 | ij_markdown_force_one_space_after_blockquote_symbol = true
561 | ij_markdown_force_one_space_after_header_symbol = true
562 | ij_markdown_force_one_space_after_list_bullet = true
563 | ij_markdown_force_one_space_between_words = true
564 | ij_markdown_format_tables = true
565 | ij_markdown_insert_quote_arrows_on_wrap = true
566 | ij_markdown_keep_indents_on_empty_lines = false
567 | ij_markdown_keep_line_breaks_inside_text_blocks = true
568 | ij_markdown_max_lines_around_block_elements = 1
569 | ij_markdown_max_lines_around_header = 1
570 | ij_markdown_max_lines_between_paragraphs = 1
571 | ij_markdown_min_lines_around_block_elements = 1
572 | ij_markdown_min_lines_around_header = 1
573 | ij_markdown_min_lines_between_paragraphs = 1
574 | ij_markdown_wrap_text_if_long = true
575 | ij_markdown_wrap_text_inside_blockquotes = true
576 |
577 | [{*.yaml,*.yml}]
578 | indent_size = 2
579 | ij_yaml_align_values_properties = do_not_align
580 | ij_yaml_autoinsert_sequence_marker = true
581 | ij_yaml_block_mapping_on_new_line = false
582 | ij_yaml_indent_sequence_value = true
583 | ij_yaml_keep_indents_on_empty_lines = false
584 | ij_yaml_keep_line_breaks = true
585 | ij_yaml_sequence_on_new_line = false
586 | ij_yaml_space_before_colon = false
587 | ij_yaml_spaces_within_braces = true
588 | ij_yaml_spaces_within_brackets = true
589 |
--------------------------------------------------------------------------------