diff --git a/.babelrc.js b/.babelrc.js deleted file mode 100644 index acc4d23..0000000 --- a/.babelrc.js +++ /dev/null @@ -1,60 +0,0 @@ -const {BUILD_TYPE} = process.env; -const isCjs = BUILD_TYPE === 'cjs'; -const isLib = BUILD_TYPE === 'lib'; - -module.exports = (api) => ({ - plugins: [ - [require('@babel/plugin-proposal-class-properties'), {loose: true}], - [require('@babel/plugin-proposal-optional-chaining'), {loose: true}], - [ - require('@babel/plugin-proposal-nullish-coalescing-operator'), - {loose: true}, - ], - ...(isLib - ? [] - : [ - [ - require('@babel/plugin-transform-runtime'), - { - regenerator: false, - }, - ], - [require('@babel/plugin-proposal-object-rest-spread'), {loose: true}], - ]), - ], - presets: [ - require('@babel/preset-typescript'), - [require('@babel/preset-react'), {useBuiltIns: true}], - ...(isLib - ? [] - : [ - [ - require('@babel/preset-env'), - { - loose: true, - modules: isCjs ? 'commonjs' : false, - shippedProposals: true, - targets: { - browsers: ['last 2 versions', 'IE 11'], - }, - useBuiltIns: false, - }, - ], - ]), - ], - ...(api.env('test') && { - presets: [ - require('@babel/preset-typescript'), - [require('@babel/preset-react'), {useBuiltIns: true}], - [ - require('@babel/preset-env'), - { - modules: 'commonjs', - targets: { - node: process.versions.node, - }, - }, - ], - ], - }), -}); diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..69ffb28 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,40 @@ +{ + "name": "react-vtree", + "image": "ghcr.io/ausginer/devimages/node:latest", + "workspaceFolder": "/workspaces/react-vtree", + "runArgs": ["--name=reactvtree_dev"], + "containerEnv": { + "PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD": "1", + "CODEX_HOME": "/workspaces/react-vtree/.agents/codex" + }, + "forwardPorts": [9876, 6006, 5176, 24678], + "remoteUser": "node", + "updateRemoteUserUID": true, + "mounts": [ + { + "source": "${localWorkspaceFolderBasename}_nodemodules", + "target": "${containerWorkspaceFolder}/node_modules", + "type": "volume" + } + ], + "customizations": { + "vscode": { + "extensions": [ + "esbenp.prettier-vscode", + "dbaeumer.vscode-eslint", + "EditorConfig.EditorConfig", + "runem.lit-plugin", + "openai.chatgpt", + "vitest.explorer", + "github.vscode-github-actions", + "oxc.oxc-vscode", + "YoavBls.pretty-ts-errors", + "acoreyj.restart-ts-eslint-server", + "TypeScriptTeam.native-preview", + "eamodio.gitlens", + "unifiedjs.vscode-mdx" + ] + } + }, + "postCreateCommand": "bash .devcontainer/post-create.sh" +} diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh new file mode 100644 index 0000000..285c153 --- /dev/null +++ b/.devcontainer/post-create.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +sudo chown -R node:node /workspaces/react-vtree/node_modules diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 3d22444..0000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -**/node_modules/**/* -**/dist/**/* -docs diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index fee67f7..0000000 --- a/.eslintrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": [ - "eslint-config-poetez/typescript-react", - "eslint-config-prettier/@typescript-eslint", - "prettier/react", - "plugin:prettier/recommended" - ], - "env": { - "browser": true, - "node": true, - "es6": true, - "jest": true - }, - "rules": { - "@typescript-eslint/promise-function-async": "off", - "@typescript-eslint/prefer-for-of": "off", - "guard-for-in": "off" - } -} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be01c95..d502e39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,41 +1,44 @@ name: CI on: + workflow_dispatch: push: branches: [master] paths: - '.github/workflows/ci.yml' + - '__stories__/**' + - '__tests__/**' + - '.storybook/**' + - '.lintstagedrc.json' + - '.oxfmtrc.json' + - '.oxlintrc.json' + - '.prettierrc.json' - 'src/**' - - 'scripts' - - '.eslintignore' - - '.eslintrc' - - '.prettierignore' - - '.prettierrc' - - 'babel.config.json' - - 'jest.config.js' + - 'eslint.config.ts' - 'package.json' - 'package-lock.json' - - 'sonar-project.properties' + - 'tsdown.config.ts' - 'tsconfig.json' - - 'tsconfig.prod.json' + - 'vitest.config.ts' pull_request: branches: [master] types: [opened, synchronize, reopened] paths: - '.github/workflows/ci.yml' + - '__stories__/**' + - '__tests__/**' + - '.storybook/**' + - '.lintstagedrc.json' + - '.oxfmtrc.json' + - '.oxlintrc.json' + - '.prettierrc.json' - 'src/**' - - 'scripts' - - '.eslintignore' - - '.eslintrc' - - '.prettierignore' - - '.prettierrc' - - 'babel.config.json' - - 'jest.config.js' + - 'eslint.config.ts' - 'package.json' - 'package-lock.json' - - 'sonar-project.properties' + - 'tsdown.config.ts' - 'tsconfig.json' - - 'tsconfig.prod.json' + - 'vitest.config.ts' jobs: testing: name: Testing and Analysis @@ -44,23 +47,15 @@ jobs: steps: - name: Checkout project code - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: fetch-depth: 0 - - name: Use Node.js 14.x - uses: actions/setup-node@v1 + - name: Use Node.js LTS + uses: actions/setup-node@v6 with: - node-version: 14.x + cache: npm + node-version: lts/* - name: Installation run: npm ci - - name: Linting + - name: Check run: npm run check - - name: Testing - run: npm run test:coverage - env: - CI: true - - name: Analysis - uses: sonarsource/sonarcloud-github-action@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.gitignore b/.gitignore index efd7a3b..802265a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,13 @@ # testing /.nyc_output /coverage +/storybook-static # production /dist /.cache +/.vite +/.vitest # misc .DS_Store @@ -17,3 +20,5 @@ npm-debug.log* yarn-debug.log* yarn-error.log* + +.agents/codex diff --git a/.lintstagedrc b/.lintstagedrc deleted file mode 100644 index b00336f..0000000 --- a/.lintstagedrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "+(.storybook|config)/*.js": ["prettier --write", "eslint --fix", "git add"], - "+(__tests__|src)/*.+(ts|tsx)": ["prettier --write", "tslint -c tslint.json -p tsconfig.json -t verbose --fix", "git add"] -} diff --git a/.lintstagedrc.json b/.lintstagedrc.json new file mode 100644 index 0000000..fd2ffe0 --- /dev/null +++ b/.lintstagedrc.json @@ -0,0 +1,4 @@ +{ + "*.{ts,tsx,mts,cts,js,mjs,cjs}": ["oxfmt --write", "eslint --fix"], + "*.{json,md}": ["oxfmt --write"] +} diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..7433314 --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +git-tag-version=false +prefer-dedupe=true +save-exact=true diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 0000000..78c8629 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,7 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "singleQuote": true, + "printWidth": 80, + "trailingComma": "all", + "embeddedLanguageFormatting": "auto" +} diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..8a686f0 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,591 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["typescript", "unicorn", "import"], + "categories": { + "correctness": "off" + }, + "env": { + "builtin": true + }, + "ignorePatterns": [ + "coverage/**/*", + "dist/**/*", + "docs/**/*", + "node_modules/**/*", + "storybook-static/**/*" + ], + "rules": { + "typescript/no-implied-eval": "error", + "typescript/only-throw-error": "error", + "typescript/prefer-promise-reject-errors": "error", + "typescript/require-await": "error", + "typescript/await-thenable": "error", + "typescript/no-array-delete": "error", + "typescript/no-base-to-string": "error", + "typescript/no-deprecated": "error", + "typescript/no-duplicate-type-constituents": [ + "error", + { + "ignoreIntersections": true + } + ], + "typescript/no-floating-promises": "error", + "typescript/no-for-in-array": "error", + "typescript/no-meaningless-void-operator": [ + "error", + { + "checkNever": false + } + ], + "typescript/no-misused-promises": [ + "error", + { + "checksVoidReturn": true, + "checksConditionals": true + } + ], + "typescript/no-misused-spread": "error", + "typescript/no-mixed-enums": "error", + "typescript/no-redundant-type-constituents": "error", + "typescript/no-unnecessary-boolean-literal-compare": "error", + "typescript/no-unnecessary-condition": "error", + "typescript/no-unnecessary-template-expression": "error", + "typescript/no-unnecessary-type-arguments": "error", + "typescript/no-unnecessary-type-assertion": "error", + "typescript/no-unsafe-call": "error", + "typescript/no-unsafe-enum-comparison": "error", + "typescript/no-unsafe-member-access": "error", + "typescript/no-unsafe-type-assertion": "error", + "typescript/no-unsafe-unary-minus": "error", + "typescript/non-nullable-type-assertion-style": "error", + "typescript/prefer-includes": "error", + "typescript/prefer-nullish-coalescing": "error", + "typescript/prefer-optional-chain": "error", + "typescript/prefer-reduce-type-parameter": "error", + "typescript/prefer-return-this-type": "error", + "typescript/promise-function-async": "error", + "typescript/related-getter-setter-pairs": "error", + "typescript/require-array-sort-compare": "error", + "typescript/restrict-plus-operands": "error", + "typescript/restrict-template-expressions": "error", + "typescript/return-await": ["error", "always"], + "typescript/switch-exhaustiveness-check": "error", + "typescript/use-unknown-in-catch-callback-variable": "error" + }, + "overrides": [ + { + "files": ["**/*.{js,jsx,mjs,cjs,mjsx,cjsx}"], + "rules": { + "array-callback-return": "error", + "constructor-super": "error", + "for-direction": "error", + "getter-return": "error", + "no-async-promise-executor": "error", + "no-await-in-loop": "error", + "no-class-assign": "error", + "no-compare-neg-zero": "error", + "no-cond-assign": ["error", "except-parens"], + "no-const-assign": "error", + "no-constant-binary-expression": "error", + "no-constant-condition": "error", + "no-constructor-return": "error", + "no-control-regex": "error", + "no-debugger": "error", + "no-dupe-class-members": "error", + "no-dupe-else-if": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-duplicate-imports": "off", + "no-empty-character-class": "error", + "no-empty-pattern": "error", + "no-ex-assign": "error", + "no-fallthrough": [ + "error", + { + "commentPattern": "^no\\sbreak" + } + ], + "no-func-assign": "error", + "no-import-assign": "error", + "no-inner-declarations": "error", + "no-invalid-regexp": [ + "error", + { + "allowConstructorFlags": ["u", "y"] + } + ], + "no-irregular-whitespace": "error", + "no-loss-of-precision": "error", + "no-misleading-character-class": "error", + "no-new-native-nonconstructor": "error", + "no-obj-calls": "error", + "no-promise-executor-return": "error", + "no-prototype-builtins": "error", + "no-self-assign": [ + "error", + { + "props": true + } + ], + "no-self-compare": "error", + "no-setter-return": "error", + "no-sparse-arrays": "error", + "no-template-curly-in-string": "error", + "no-this-before-super": "error", + "no-unassigned-vars": "error", + "no-undef": "error", + "no-unmodified-loop-condition": "error", + "no-unreachable": "error", + "no-unsafe-finally": "error", + "no-unsafe-negation": "error", + "no-unsafe-optional-chaining": [ + "error", + { + "disallowArithmeticOperators": true + } + ], + "no-unused-private-class-members": "error", + "no-unused-vars": [ + "error", + { + "args": "all", + "argsIgnorePattern": "^_", + "caughtErrors": "all", + "caughtErrorsIgnorePattern": "^_", + "ignoreRestSiblings": true, + "vars": "all", + "varsIgnorePattern": "^_" + } + ], + "no-useless-backreference": "error", + "use-isnan": "error", + "valid-typeof": [ + "error", + { + "requireStringLiterals": false + } + ], + "accessor-pairs": "error", + "arrow-body-style": ["error", "as-needed"], + "block-scoped-var": "off", + "capitalized-comments": "off", + "class-methods-use-this": "error", + "complexity": "off", + "default-case": [ + "error", + { + "commentPattern": "^no\\sdefault" + } + ], + "default-case-last": "error", + "default-param-last": "error", + "eqeqeq": [ + "error", + "always", + { + "null": "ignore" + } + ], + "func-names": ["error", "always"], + "func-style": [ + "error", + "declaration", + { + "allowArrowFunctions": true + } + ], + "grouped-accessor-pairs": ["error", "getBeforeSet"], + "guard-for-in": "off", + "id-length": "off", + "init-declarations": "off", + "max-classes-per-file": ["error", 3], + "max-depth": ["error", 4], + "max-lines": "off", + "max-lines-per-function": "off", + "max-nested-callbacks": "off", + "max-params": [ + "error", + { + "max": 4 + } + ], + "max-statements": "off", + "new-cap": "off", + "no-alert": "error", + "no-array-constructor": "error", + "no-bitwise": "error", + "no-caller": "error", + "no-case-declarations": "error", + "no-console": [ + "error", + { + "allow": ["warn", "error"] + } + ], + "no-continue": "off", + "no-delete-var": "error", + "no-div-regex": "error", + "no-else-return": "error", + "no-empty": [ + "error", + { + "allowEmptyCatch": true + } + ], + "no-empty-function": "off", + "no-empty-static-block": "error", + "no-eq-null": "off", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-extra-boolean-cast": "error", + "no-extra-label": "off", + "no-global-assign": "error", + "no-implicit-coercion": [ + "error", + { + "allow": ["!!"] + } + ], + "no-inline-comments": "off", + "no-iterator": "error", + "no-label-var": "off", + "no-labels": "error", + "no-lone-blocks": "error", + "no-lonely-if": "error", + "no-loop-func": "error", + "no-magic-numbers": "off", + "no-multi-assign": "error", + "no-multi-str": "error", + "no-negated-condition": "off", + "no-nested-ternary": "off", + "no-new": "error", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-nonoctal-decimal-escape": "error", + "no-object-constructor": "error", + "no-param-reassign": [ + "error", + { + "props": false + } + ], + "no-plusplus": [ + "error", + { + "allowForLoopAfterthoughts": true + } + ], + "no-proto": "error", + "no-redeclare": "off", + "no-regex-spaces": "error", + "no-restricted-globals": "off", + "no-restricted-imports": "off", + "no-return-assign": ["error", "always"], + "no-script-url": "error", + "no-sequences": "error", + "no-shadow": "error", + "no-shadow-restricted-names": "error", + "no-ternary": "off", + "no-undefined": "off", + "no-unneeded-ternary": "error", + "no-unused-expressions": "error", + "no-unused-labels": "off", + "no-useless-call": "error", + "no-useless-catch": "error", + "no-useless-computed-key": "error", + "no-useless-concat": "off", + "no-useless-constructor": "error", + "no-useless-escape": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-var": "error", + "no-void": "error", + "no-warning-comments": "off", + "no-with": "error", + "operator-assignment": ["error", "always"], + "prefer-const": [ + "error", + { + "ignoreReadBeforeAssign": true + } + ], + "prefer-exponentiation-operator": "error", + "prefer-numeric-literals": "error", + "prefer-object-has-own": "error", + "prefer-object-spread": "error", + "prefer-rest-params": "error", + "prefer-spread": "error", + "prefer-template": "error", + "preserve-caught-error": [ + "error", + { + "requireCatchParameter": true + } + ], + "radix": "error", + "require-yield": "error", + "sort-imports": "off", + "sort-keys": "off", + "sort-vars": "off", + "symbol-description": "off", + "unicode-bom": ["error", "never"], + "vars-on-top": "off", + "yoda": ["error", "never"] + } + }, + { + "files": [ + "**/*.{js,jsx,mjs,cjs,mjsx,cjsx}", + "**/*.{ts,tsx,mts,cts,mtsx,ctsx}" + ], + "rules": { + "class-methods-use-this": [ + "error", + { + "ignoreOverrideMethods": true, + "ignoreClassesThatImplementAnInterface": true + } + ], + "default-param-last": "error", + "init-declarations": "off", + "max-params": [ + "error", + { + "max": 4 + } + ], + "no-dupe-class-members": "error", + "no-empty-function": "off", + "no-loop-func": "error", + "no-loss-of-precision": "off", + "no-magic-numbers": "off", + "no-redeclare": "off", + "no-restricted-imports": "off", + "no-shadow": "error", + "no-unused-expressions": "error", + "no-unused-private-class-members": "off", + "no-unused-vars": [ + "error", + { + "args": "all", + "argsIgnorePattern": "^_", + "caughtErrors": "all", + "caughtErrorsIgnorePattern": "^_", + "ignoreRestSiblings": true, + "vars": "all", + "varsIgnorePattern": "^_" + } + ], + "no-useless-constructor": "error", + "typescript/adjacent-overload-signatures": "error", + "typescript/array-type": [ + "error", + { + "default": "array-simple", + "readonly": "array-simple" + } + ], + "typescript/ban-ts-comment": [ + "error", + { + "ts-expect-error": "allow-with-description", + "ts-ignore": "allow-with-description", + "ts-nocheck": "allow-with-description", + "ts-check": "allow-with-description", + "minimumDescriptionLength": 3 + } + ], + "typescript/ban-tslint-comment": "error", + "typescript/class-literal-property-style": ["error", "fields"], + "typescript/consistent-generic-constructors": "error", + "typescript/consistent-indexed-object-style": ["error", "record"], + "typescript/consistent-type-assertions": [ + "error", + { + "assertionStyle": "as", + "objectLiteralTypeAssertions": "allow-as-parameter" + } + ], + "typescript/consistent-type-definitions": "off", + "typescript/consistent-type-imports": [ + "error", + { + "prefer": "type-imports", + "disallowTypeAnnotations": true, + "fixStyle": "inline-type-imports" + } + ], + "typescript/no-confusing-non-null-assertion": "error", + "typescript/no-duplicate-enum-values": "error", + "typescript/no-dynamic-delete": "error", + "typescript/no-empty-object-type": "error", + "typescript/no-explicit-any": "off", + "typescript/no-extra-non-null-assertion": "error", + "typescript/no-extraneous-class": "error", + "typescript/no-import-type-side-effects": "error", + "typescript/no-inferrable-types": [ + "error", + { + "ignoreParameters": true, + "ignoreProperties": true + } + ], + "typescript/no-invalid-void-type": "error", + "typescript/no-misused-new": "error", + "typescript/no-namespace": [ + "error", + { + "allowDefinitionFiles": true + } + ], + "typescript/no-non-null-asserted-nullish-coalescing": "error", + "typescript/no-non-null-asserted-optional-chain": "error", + "typescript/no-non-null-assertion": "off", + "typescript/no-require-imports": "error", + "typescript/no-restricted-types": "error", + "typescript/no-this-alias": [ + "error", + { + "allowDestructuring": true, + "allowedNames": ["self"] + } + ], + "typescript/no-unnecessary-type-constraint": "error", + "typescript/no-unsafe-declaration-merging": "off", + "typescript/no-unsafe-function-type": "error", + "typescript/no-useless-empty-export": "error", + "typescript/no-wrapper-object-types": "error", + "typescript/parameter-properties": "error", + "typescript/prefer-as-const": "error", + "typescript/prefer-enum-initializers": "error", + "typescript/prefer-for-of": "error", + "typescript/prefer-function-type": "error", + "typescript/prefer-literal-enum-member": [ + "error", + { + "allowBitwiseExpressions": true + } + ], + "typescript/prefer-namespace-keyword": "off", + "typescript/triple-slash-reference": [ + "error", + { + "path": "never", + "types": "never", + "lib": "never" + } + ], + "typescript/unified-signatures": "error", + "no-array-constructor": "error", + "no-use-before-define": [ + "error", + { + "classes": true, + "functions": true, + "variables": true, + "typedefs": true + } + ] + } + }, + { + "files": ["**/*.{ts,tsx,mts,cts,mtsx,ctsx}"], + "rules": { + "constructor-super": "off", + "getter-return": "off", + "no-const-assign": "off", + "no-dupe-keys": "off", + "no-func-assign": "off", + "no-import-assign": "off", + "no-obj-calls": "off", + "no-setter-return": "off", + "no-this-before-super": "off", + "no-undef": "off", + "no-unreachable": "off", + "no-unsafe-negation": "off", + "valid-typeof": "off", + "typescript/explicit-function-return-type": "off", + "typescript/explicit-module-boundary-types": [ + "error", + { + "allowArgumentsExplicitlyTypedAsAny": true, + "allowDirectConstAssertionInArrowFunctions": true, + "allowHigherOrderFunctions": true, + "allowTypedFunctionExpressions": true + } + ], + "typescript/no-unnecessary-parameter-property-assignment": "off" + } + }, + { + "files": ["**/*.{ts,tsx,mts,cts}"], + "rules": { + "import/consistent-type-specifier-style": "off", + "import/default": "error", + "import/export": "error", + "import/exports-last": "off", + "import/extensions": "off", + "import/first": "error", + "import/group-exports": "off", + "import/max-dependencies": "off", + "import/named": "error", + "import/namespace": "error", + "import/no-absolute-path": [ + "error", + { + "esmodule": false, + "commonjs": true + } + ], + "import/no-amd": "off", + "import/no-anonymous-default-export": "error", + "import/no-commonjs": "off", + "import/no-cycle": "error", + "import/no-default-export": "off", + "import/no-dynamic-require": "off", + "import/no-empty-named-blocks": "error", + "import/no-mutable-exports": "error", + "import/no-named-as-default": "off", + "import/no-named-as-default-member": "error", + "import/no-named-default": "error", + "import/no-named-export": "off", + "import/no-namespace": "off", + "import/no-nodejs-modules": "off", + "import/no-relative-parent-imports": "off", + "import/no-self-import": "error", + "import/no-webpack-loader-syntax": "error", + "import/unambiguous": "error" + } + }, + { + "files": [ + "**/*.spec.js", + "**/*.spec.ts", + "**/*.spec.jsx", + "**/*.spec.tsx", + "**/*.test.js", + "**/*.test.ts", + "**/*.test.jsx", + "**/*.test.tsx" + ], + "rules": { + "max-classes-per-file": "off", + "no-unused-expressions": "off" + } + }, + { + "files": ["**/*.{ts,tsx,mts,cts}"], + "rules": { + "no-shadow": "allow", + // Broken. Cannot disable inline + "import/unambiguous": "allow", + // Broken. Many false positives + "typescript/no-unnecessary-condition": "allow", + // I use for loop a loot for perf reasons + "typescript/prefer-for-of": "off", + "typescript/no-empty-object-type": "off" + } + } + ] +} diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index e0afa49..0000000 --- a/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "bracketSpacing": false, - "printWidth": 80, - "trailingComma": "all", - "tabWidth": 2, - "singleQuote": true -} diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..8756645 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "singleQuote": true, + "printWidth": 80, + "trailingComma": "all", + "embeddedLanguageFormatting": "auto" +} diff --git a/.storybook/addons.js b/.storybook/addons.js deleted file mode 100644 index a9c4098..0000000 --- a/.storybook/addons.js +++ /dev/null @@ -1,2 +0,0 @@ -require('@storybook/addon-knobs/register'); -require('@storybook/addon-options/register'); diff --git a/.storybook/config.js b/.storybook/config.js deleted file mode 100644 index 76bf651..0000000 --- a/.storybook/config.js +++ /dev/null @@ -1,11 +0,0 @@ -const {addParameters, configure} = require('@storybook/react'); - -addParameters({ - options: { - addonPanelInRight: true, - name: 'React Virtualized Tree', - selectedPanel: 'knobs', - }, -}); - -configure(() => require('../__stories__'), module); diff --git a/.storybook/main.ts b/.storybook/main.ts new file mode 100644 index 0000000..f80da49 --- /dev/null +++ b/.storybook/main.ts @@ -0,0 +1,9 @@ +import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { + addons: [], + framework: '@storybook/react-vite', + stories: ['../__stories__/**/*.story.tsx'], +}; + +export default config; diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx new file mode 100644 index 0000000..4dfb07d --- /dev/null +++ b/.storybook/preview.tsx @@ -0,0 +1,24 @@ +import type { Preview } from '@storybook/react-vite'; + +const preview: Preview = { + decorators: [ + (Story) => ( +
+
+ +
+
+ ), + ], + parameters: { + layout: 'fullscreen', + }, +}; + +export default preview; diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js deleted file mode 100644 index 002f1ee..0000000 --- a/.storybook/webpack.config.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = ({config}) => { - config.devtool = 'eval'; - - config.module.rules.push({ - test: /\.(ts|tsx)$/, - loader: require.resolve('babel-loader'), - }); - - config.resolve.extensions.push('.ts', '.tsx'); - - return config; -}; diff --git a/__stories__/AsyncData.story.tsx b/__stories__/AsyncData.story.tsx index 51bdfb7..b575eb8 100644 --- a/__stories__/AsyncData.story.tsx +++ b/__stories__/AsyncData.story.tsx @@ -1,25 +1,14 @@ -/* eslint-disable max-depth */ -import {boolean, number, withKnobs} from '@storybook/addon-knobs'; -import {storiesOf} from '@storybook/react'; -import React, {FC, useCallback, useMemo, useRef, useState} from 'react'; -import AutoSizer from 'react-virtualized-auto-sizer'; +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { type FC, useCallback, useMemo, useRef, useState } from 'react'; +import { AutoSizer } from 'react-virtualized-auto-sizer'; import { - FixedSizeNodeData, - FixedSizeNodePublicState, + type FixedSizeNodeData, + type FixedSizeNodePublicState, FixedSizeTree, - TreeWalker, - TreeWalkerValue, -} from '../src'; -import {NodeComponentProps} from '../src/Tree'; -import {AsyncTaskScheduler} from './utils'; - -document.body.style.margin = '0'; -document.body.style.display = 'flex'; -document.body.style.minHeight = '100vh'; - -const root = document.getElementById('root')!; -root.style.margin = '10px 0 0 10px'; -root.style.flex = '1'; +} from '../src/FixedSizeTree.tsx'; +import type { NodeComponentProps } from '../src/Tree.tsx'; +import type { TreeWalker, TreeWalkerValue } from '../src/Tree.tsx'; +import { AsyncTaskScheduler } from './utils.ts'; type TreeNode = Readonly<{ children: TreeNode[]; @@ -31,7 +20,7 @@ type TreeNode = Readonly<{ type TreeData = FixedSizeNodeData & Readonly<{ downloaded: boolean; - download: () => Promise; + download(): Promise; isLeaf: boolean; name: string; nestingLevel: number; @@ -64,8 +53,8 @@ const createNode = ( return node; }; -const defaultTextStyle = {marginLeft: 10}; -const defaultButtonStyle = {fontFamily: 'Courier New'}; +const defaultTextStyle = { marginLeft: 10 }; +const defaultButtonStyle = { fontFamily: 'Courier New' }; type NodeMeta = Readonly<{ nestingLevel: number; @@ -90,17 +79,27 @@ const getNodeData = ( node, }); -const Node: FC ->> = ({ - data: {download, downloaded, isLeaf, name, nestingLevel}, +const Node: FC< + NodeComponentProps> +> = ({ + data: { download, downloaded, isLeaf, name, nestingLevel }, isOpen, style, setOpen, }) => { const [isLoading, setLoading] = useState(false); + const handleClick = async () => { + if (!downloaded) { + setLoading(true); + await download(); + await setOpen(!isOpen); + setLoading(false); + } else { + await setOpen(!isOpen); + } + }; + return (