diff --git a/app/src/App.tsx b/app/src/App.tsx
index 8ce26b50..94af6028 100644
--- a/app/src/App.tsx
+++ b/app/src/App.tsx
@@ -28,14 +28,16 @@ onSnapshot(mymodel, snap => {
})
// used in ViewContainer files to get the width
-export function useWidthSetter(view: { setWidth: (arg: number) => void }) {
+function useWidthSetter(view: { setWidth: (arg: number) => void }) {
const [ref, { width }] = useMeasure()
useEffect(() => {
if (width && isAlive(view)) {
// sets after a requestAnimationFrame
// https://stackoverflow.com/a/58701523/2129219 avoids ResizeObserver
// loop error being shown during development
- requestAnimationFrame(() => view.setWidth(width))
+ requestAnimationFrame(() => {
+ view.setWidth(width)
+ })
}
}, [view, width])
return ref
diff --git a/eslint.config.mjs b/eslint.config.mjs
index e6ef596b..5a524b77 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,60 +1,26 @@
-import { fixupConfigRules } from '@eslint/compat'
-import globals from 'globals'
-import tsParser from '@typescript-eslint/parser'
-import path from 'node:path'
-import { fileURLToPath } from 'node:url'
-import js from '@eslint/js'
-import { FlatCompat } from '@eslint/eslintrc'
+import eslint from '@eslint/js'
+import eslintPluginReact from 'eslint-plugin-react'
+import eslintPluginReactHooks from 'eslint-plugin-react-hooks'
+import eslintPluginReactRefresh from 'eslint-plugin-react-refresh'
+import eslintPluginUnicorn from 'eslint-plugin-unicorn'
+import tseslint from 'typescript-eslint'
-const __filename = fileURLToPath(import.meta.url)
-const __dirname = path.dirname(__filename)
-const compat = new FlatCompat({
- baseDirectory: __dirname,
- recommendedConfig: js.configs.recommended,
- allConfig: js.configs.all,
-})
-
-export default [
+export default tseslint.config(
{
ignores: [
- '**/coverage',
- '**/node_modules/',
- '**/dist/',
- '**/bundle/',
- '**/.eslintrc.js',
+ '**/build/**/*',
+ '**/dist/**/*',
+ '**/esm/**/*',
+ '**/public/**/*',
+ '**/bundle/**/*',
'lib/output-version.js',
],
},
- ...fixupConfigRules(
- compat.extends(
- 'eslint:recommended',
- 'plugin:@typescript-eslint/recommended',
- 'plugin:@typescript-eslint/recommended-type-checked',
- 'plugin:@typescript-eslint/stylistic-type-checked',
- 'plugin:unicorn/recommended',
- 'plugin:react/recommended',
- 'plugin:react-hooks/recommended',
- 'plugin:prettier/recommended',
- ),
- ),
{
languageOptions: {
- globals: {
- ...globals.browser,
- ...globals.node,
- ...globals.jest,
- },
-
- parser: tsParser,
- ecmaVersion: 5,
- sourceType: 'commonjs',
-
parserOptions: {
- ecmaFeatures: {
- jsx: true,
- },
-
- project: './tsconfig.json',
+ project: ['./tsconfig.json'],
+ tsconfigRootDir: import.meta.dirname,
},
},
@@ -63,38 +29,55 @@ export default [
version: 'detect',
},
},
-
+ },
+ eslint.configs.recommended,
+ ...tseslint.configs.recommended,
+ ...tseslint.configs.stylisticTypeChecked,
+ ...tseslint.configs.strictTypeChecked,
+ eslintPluginReact.configs.flat.recommended,
+ {
+ plugins: {
+ 'react-hooks': eslintPluginReactHooks,
+ },
+ rules: eslintPluginReactHooks.configs.recommended.rules,
+ },
+ eslintPluginUnicorn.configs['flat/recommended'],
+ {
+ // in main config for TSX/JSX source files
+ plugins: {
+ 'react-refresh': eslintPluginReactRefresh,
+ },
+ rules: {},
+ },
+ {
rules: {
- 'no-redeclare': 'off',
- '@typescript-eslint/ban-ts-comment': 'off',
- '@typescript-eslint/explicit-function-return-type': 'off',
- '@typescript-eslint/explicit-module-boundary-types': 'off',
- '@typescript-eslint/no-base-to-string': 'off',
- '@typescript-eslint/prefer-nullish-coalescing': 'off',
- '@typescript-eslint/no-empty-function': 'off',
- '@typescript-eslint/no-unused-vars': [
+ 'no-empty': 'off',
+ 'no-console': [
'warn',
{
- argsIgnorePattern: '^_',
- ignoreRestSiblings: true,
- caughtErrors: 'none',
+ allow: ['error', 'warn'],
},
],
- '@typescript-eslint/no-floating-promises': 'error',
- '@typescript-eslint/restrict-template-expressions': 'off',
- '@typescript-eslint/restrict-plus-operands': 'off',
- '@typescript-eslint/no-misused-promises': 'off',
- '@typescript-eslint/require-await': 'off',
- '@typescript-eslint/unbound-method': 'off',
- '@typescript-eslint/no-unused-expressions': 'off',
- '@typescript-eslint/no-unsafe-member-access': 'off',
- '@typescript-eslint/no-unsafe-argument': 'off',
- '@typescript-eslint/no-unsafe-assignment': 'off',
- '@typescript-eslint/no-unsafe-call': 'off',
- '@typescript-eslint/no-unsafe-return': 'off',
- 'no-unexpected-multiline': 'error',
+ 'no-underscore-dangle': 'off',
+ curly: 'error',
+ semi: ['error', 'never'],
+ 'spaced-comment': [
+ 'error',
+ 'always',
+ {
+ markers: ['/'],
+ },
+ ],
+
+ 'react-refresh/only-export-components': 'warn',
+ 'react/no-unescaped-entities': 'off',
+ 'react/prop-types': 'off',
+
+ 'unicorn/prefer-structured-clone': 'off',
'unicorn/no-new-array': 'off',
+ 'unicorn/no-empty-file': 'off',
'unicorn/prefer-type-error': 'off',
+ 'unicorn/prefer-modern-math-apis': 'off',
'unicorn/prefer-node-protocol': 'off',
'unicorn/no-unreadable-array-destructuring': 'off',
'unicorn/no-abusive-eslint-disable': 'off',
@@ -123,39 +106,45 @@ export default [
'unicorn/relative-url-style': 'off',
'unicorn/prefer-math-trunc': 'off',
'unicorn/prefer-query-selector': 'off',
+ 'unicorn/no-negated-condition': 'off',
'unicorn/switch-case-braces': 'off',
'unicorn/prefer-switch': 'off',
'unicorn/better-regex': 'off',
'unicorn/no-for-loop': 'off',
'unicorn/escape-case': 'off',
'unicorn/prefer-number-properties': 'off',
- curly: 'error',
- 'no-use-before-define': 'off',
- 'no-global-assign': 'warn',
+ 'unicorn/no-process-exit': 'off',
+ 'unicorn/prefer-at': 'off',
+ 'unicorn/prefer-string-replace-all': 'off',
+ 'unicorn/no-array-reduce': 'off',
- 'no-console': [
+ '@typescript-eslint/no-explicit-any': 'off',
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
+ '@typescript-eslint/ban-ts-comment': 'off',
+ '@typescript-eslint/no-unnecessary-type-parameters': 'off',
+ '@typescript-eslint/no-base-to-string': 'off',
+ '@typescript-eslint/no-unsafe-member-access': 'off',
+ '@typescript-eslint/no-unsafe-argument': 'off',
+ '@typescript-eslint/no-unsafe-assignment': 'off',
+ '@typescript-eslint/restrict-plus-operands': 'off',
+ '@typescript-eslint/no-unsafe-call': 'off',
+ '@typescript-eslint/no-unsafe-return': 'off',
+ '@typescript-eslint/prefer-nullish-coalescing': 'off',
+ '@typescript-eslint/no-non-null-assertion': 'off',
+ '@typescript-eslint/require-await': 'off',
+ '@typescript-eslint/restrict-template-expressions': 'off',
+ '@typescript-eslint/no-empty-function': 'off',
+ '@typescript-eslint/no-extraneous-class': 'off',
+ '@typescript-eslint/unbound-method': 'off',
+ '@typescript-eslint/no-dynamic-delete': 'off',
+ '@typescript-eslint/no-unused-vars': [
'warn',
{
- allow: ['error', 'warn'],
- },
- ],
-
- 'no-debugger': 'warn',
- 'no-undef': 'error',
- 'react/no-danger': 'warn',
- 'react/prop-types': 'off',
- 'react/destructuring-assignment': 'error',
- 'react/no-unused-prop-types': 'error',
- 'react/no-unused-state': 'error',
- 'react/prefer-stateless-function': 'error',
-
- 'spaced-comment': [
- 'error',
- 'always',
- {
- markers: ['/'],
+ argsIgnorePattern: '^_',
+ ignoreRestSiblings: true,
+ caughtErrors: 'none',
},
],
},
},
-]
+)
diff --git a/lib/docgen/generateStateModelDocs.ts b/lib/docgen/generateStateModelDocs.ts
index 030ed6c1..ee41d969 100644
--- a/lib/docgen/generateStateModelDocs.ts
+++ b/lib/docgen/generateStateModelDocs.ts
@@ -113,7 +113,7 @@ function generateStateModelDocs(files: string[]) {
if (model) {
const getterstr = `${getters.length ? `### ${model.name} - Getters` : ''}\n${getters
.sort((a, b) => a.name.localeCompare(b.name))
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+
.map(({ name, docs, signature }: any) => {
return `#### getter: ${name}
@@ -129,7 +129,7 @@ ${signature || ''}
const methodstr = `${methods.length ? `### ${model.name} - Methods` : ''}\n${methods
.sort((a, b) => a.name.localeCompare(b.name))
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+
.map(({ name, docs, signature }: any) => {
return `#### method: ${name}
@@ -145,7 +145,7 @@ ${name}: ${signature || ''}
const propertiesstr = `${properties.length ? `### ${model.name} - Properties` : ''}\n${properties
.sort((a, b) => a.name.localeCompare(b.name))
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+
.map(({ name, docs, code, signature }: any) => {
return `#### property: ${name}
@@ -163,7 +163,7 @@ ${code}
const actionstr = `${actions.length ? `### ${model.name} - Actions` : ''}\n${actions
.sort((a, b) => a.name.localeCompare(b.name))
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+
.map(({ name, docs, signature }: any) => {
return `#### action: ${name}
diff --git a/lib/src/colorSchemes.ts b/lib/src/colorSchemes.ts
index 32d97b1d..e5d0fac3 100644
--- a/lib/src/colorSchemes.ts
+++ b/lib/src/colorSchemes.ts
@@ -357,7 +357,7 @@ export function getClustalXColor(
row: string,
col: number,
) {
- const l = model.columns[row][col]
+ const l = model.columns[row]![col]!
const {
W = 0,
L = 0,
@@ -504,7 +504,7 @@ export function getPercentIdentityColor(
row: string,
col: number,
) {
- const l = model.columns[row][col]
+ const l = model.columns[row]![col]!
const entries = Object.entries(stats)
let ent = 0
let letter = ''
diff --git a/lib/src/components/Loading.tsx b/lib/src/components/Loading.tsx
index 14c59970..953e4de7 100644
--- a/lib/src/components/Loading.tsx
+++ b/lib/src/components/Loading.tsx
@@ -19,7 +19,13 @@ const Reset = observer(function ({
return (
-
diff --git a/lib/src/components/ResizeHandles.tsx b/lib/src/components/ResizeHandles.tsx
index 8e57712f..581ce083 100644
--- a/lib/src/components/ResizeHandles.tsx
+++ b/lib/src/components/ResizeHandles.tsx
@@ -57,7 +57,9 @@ export const VerticalResizeHandle = observer(function ({
return (
setMouseDragging(true)}
+ onMouseDown={() => {
+ setMouseDragging(true)
+ }}
style={{
cursor: 'ew-resize',
height: '100%',
@@ -123,7 +125,9 @@ export const HorizontalResizeHandle = observer(function ({
return (
setMouseDragging(true)}
+ onMouseDown={() => {
+ setMouseDragging(true)
+ }}
style={{
cursor: 'ns-resize',
width: '100%',
diff --git a/lib/src/components/SequenceTextArea.tsx b/lib/src/components/SequenceTextArea.tsx
index 3442d044..72735f99 100644
--- a/lib/src/components/SequenceTextArea.tsx
+++ b/lib/src/components/SequenceTextArea.tsx
@@ -25,7 +25,7 @@ export default function SequenceTextArea({ str }: { str: [string, string][] }) {
const [showEmpty, setShowEmpty] = useState(false)
const disp = str
- .map(([s1, s2]) => [s1, showGaps ? s2 : s2.replaceAll('-', '')])
+ .map(([s1, s2]) => [s1, showGaps ? s2 : s2.replaceAll('-', '')] as const)
.filter(f => (showEmpty ? true : !!f[1]))
.map(([s1, s2]) => `>${s1}\n${showGaps ? s2 : s2.replaceAll('-', '')}`)
.join('\n')
@@ -37,7 +37,9 @@ export default function SequenceTextArea({ str }: { str: [string, string][] }) {
onClick={() => {
copy(disp)
setCopied(true)
- setTimeout(() => setCopied(false), 500)
+ setTimeout(() => {
+ setCopied(false)
+ }, 500)
}}
>
{copied ? 'Copied!' : 'Copy to clipboard'}
@@ -45,12 +47,16 @@ export default function SequenceTextArea({ str }: { str: [string, string][] }) {
setShowGaps(!showGaps)}
+ onChange={() => {
+ setShowGaps(!showGaps)
+ }}
/>
setShowEmpty(!showEmpty)}
+ onChange={() => {
+ setShowEmpty(!showEmpty)
+ }}
/>
()
@@ -53,7 +53,9 @@ export const TrackLabel = observer(function ({
width: trackLabelHeight,
height: trackLabelHeight,
}}
- onClick={event => setAnchorEl(event.currentTarget)}
+ onClick={event => {
+ setAnchorEl(event.currentTarget)
+ }}
>
@@ -62,7 +64,9 @@ export const TrackLabel = observer(function ({
anchorEl={anchorEl}
transitionDuration={0}
open
- onClose={() => setAnchorEl(undefined)}
+ onClose={() => {
+ setAnchorEl(undefined)
+ }}
>