diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c23b51fe3f..7ba1c4e3ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -323,7 +323,7 @@ jobs: mv /tmp/docs/.buildx-cache-new /tmp/docs/.buildx-cache e2e: - timeout-minutes: 10 + timeout-minutes: 20 runs-on: ubuntu-latest needs: [typecheck, format] env: diff --git a/.oxlintrc.json b/.oxlintrc.json index 0891e81e20..514a44b619 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -1,64 +1,216 @@ { "$schema": "./node_modules/oxlint/configuration_schema.json", + "ignorePatterns": [ + "**/app.config.d.ts", + "**/package.config.d.ts", + "eslint.config.mjs", + "next.config.js", + "*.d.ts", + "svgo.config.mjs" + ], "categories": { - "correctness": "error", - "nursery": "off", - "pedantic": "error", - "perf": "error", - "restriction": "error", - "style": "error", - "suspicious": "error" + "correctness": "deny", + "style": "deny", + "suspicious": "deny", + "perf": "deny", + "pedantic": "deny", + "restriction": "deny", + "nursery": "off" }, "plugins": [ "import", - "eslint", "node", - "react-perf", + "oxc", "react", "typescript", - "unicorn" + "unicorn", + "jsx-a11y" ], "overrides": [ { - "files": ["**/__stories__/**/*.{ts,tsx}", "**/__tests__/**/*.{ts,tsx}"], + "files": ["**/__stories__/**/*.{ts,tsx}", "**/__tests__/**/*.{ts,tsx}", ".storybook/**/*.{ts,tsx}"], "rules": { - "react/jsx-key": "off", - "no-console": "off", - "no-alert": "off" + "eslint/no-console": "off", + "eslint/no-alert": "off", + "import/no-anonymous-default-export": "off", + "import/no-unassigned-import": "off" } }, { - "files": ["**/__tests__/**/*.{ts,tsx}", "setup.ts"], - "plugins": ["vitest"] + "files": [ + "**/__tests__/**/*.{ts,tsx}", + "**/__mocks__/**/*.{ts,tsx}", + "**/*.test.{ts,tsx}", + "test-utils.tsx", + "setup.ts", + "vitest.setup.ts", + "**/vitest.setup.ts", + "*.config.ts" + ], + "plugins": ["import", "oxc", "vitest"], + "rules": { + "@typescript-eslint/consistent-type-imports": "off", + "import/no-namespace": "off", + "import/export": "off", + "import/no-anonymous-default-export": "off", + "import/no-unassigned-import": "off", + "jsx_a11y/label-has-associated-control": "off", + "vitest/prefer-lowercase-title": "error" + } } ], "rules": { - "@typescript-eslint/no-unused-expressions": "error", - "@typescript-eslint/ban-tslint-comment": "error", - "@typescript-eslint/consistent-indexed-object-style": "error", + "jsx_a11y/label-has-associated-control": "off", + "jsx_a11y/no-autofocus": "off", + "jsx_a11y/prefer-tag-over-role": "off", + "import/default": "error", + "import/export": "off", + "import/exports-last": "off", + "import/max-dependencies": "off", + "import/named": "error", + "import/no-amd": "error", + "import/consistent-type-specifier-style": "error", + "import/group-exports": "off", + "import/import-no-namespace": "off", + "import/namespace": "off", + "import/no-cycle": "error", + "import/no-default-export": "off", + "import/no-duplicates": "error", + "import/no-named-as-default-member": "error", + "import/no-named-as-default": "error", + "import/no-self-import": "error", + "import/no-unassigned-import": "error", + "import/no-unused-modules": "off", + "import/prefer-default-export": "off", + "import/no-namespace": "off", + "import/unambiguous": "error", + "@typescript-eslint/adjacent-overload-signatures": "error", + "@typescript-eslint/array-type": "error", + "@typescript-eslint/ban-ts-comment": "error", + "@typescript-eslint/ban-tslint-comment": "off", + "@typescript-eslint/ban-types": "error", + "@typescript-eslint/consistent-indexed-object-style": "off", "@typescript-eslint/consistent-type-definitions": ["error", "type"], + "@typescript-eslint/consistent-type-exports": "error", "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-duplicate-enum-values": "error", + "@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/no-magic-numbers": "off", + "@typescript-eslint/no-extra-non-null-assertion": "error", + "@typescript-eslint/no-misused-new": "error", + "@typescript-eslint/no-namespace": "error", + "@typescript-eslint/no-non-null-asserted-optional-chain": "error", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-this-alias": "error", + "@typescript-eslint/no-unnecessary-type-constraint": "error", + "@typescript-eslint/no-unsafe-declaration-merging": "error", + "@typescript-eslint/no-var-requires": "error", + "@typescript-eslint/prefer-as-const": "error", + "@typescript/no-unsafe-member-access": "error", "@typescript-eslint/prefer-enum-initializers": "off", + "@typescript-eslint/prefer-for-of": "error", "@typescript-eslint/prefer-function-type": "off", "@typescript-eslint/prefer-literal-enum-member": "off", + "@typescript-eslint/prefer-ts-expect-error": "off", + "@typescript-eslint/triple-slash-reference": "error", + "eslint/yoda": "error", + "eslint/array-callback-return": "error", + "eslint/constructor-super": "error", + "eslint/default-case-last": "error", "eslint/default-param-last": "off", + "eslint/eqeqeq": "error", + "eslint/for-direction": "error", + "eslint/getter-return": "error", + "eslint/guard-for-in": "error", + "eslint/max-classes-per-file": "error", "eslint/max-lines": "off", "eslint/max-params": "off", + "eslint/no-array-constructor": "error", + "eslint/no-async-promise-executor": "error", "eslint/no-await-in-loop": "off", + "eslint/no-bitwise": "error", + "eslint/no-caller": "error", + "eslint/id-length": "off", + "eslint/no-case-declarations": "error", + "eslint/no-class-assign": "error", + "eslint/no-compare-neg-zero": "error", + "eslint/no-cond-assign": "error", + "eslint/no-console": "error", + "eslint/no-const-assign": "error", + "eslint/no-constant-binary-expression": "error", + "eslint/no-constant-condition": "error", + "eslint/no-continue": "error", + "eslint/no-control-regex": "error", + "eslint/no-debugger": "error", + "eslint/no-delete-var": "error", + "eslint/no-dupe-class-members": "error", + "eslint/no-dupe-else-if": "error", + "eslint/no-dupe-keys": "error", + "eslint/no-duplicate-case": "error", "eslint/no-duplicate-imports": "off", + "eslint/no-empty-character-class": "error", "eslint/no-empty-function": "off", + "eslint/no-empty-pattern": "error", + "eslint/no-empty-static-block": "error", + "eslint/no-empty": "error", + "eslint/no-eq-null": "error", + "eslint/no-eval": "error", + "eslint/no-ex-assign": "error", + "eslint/no-extra-boolean-cast": "error", + "eslint/no-fallthrough": "error", + "eslint/no-func-assign": "error", + "eslint/no-global-assign": "error", + "eslint/no-import-assign": "error", + "eslint/no-inner-declarations": "error", + "eslint/no-irregular-whitespace": "error", + "eslint/no-iterator": "error", + "eslint/no-loss-of-precision": "error", "eslint/no-magic-numbers": "off", + "eslint/no-mixed-operators": "error", + "eslint/no-new-native-nonconstructor": "error", + "eslint/no-new-symbol": "error", + "eslint/no-new-wrappers": "error", + "eslint/no-nonoctal-decimal-escape": "error", + "eslint/no-obj-calls": "error", + "eslint/no-proto": "error", + "eslint/no-prototype-builtins": "error", + "eslint/no-redeclare": "error", + "eslint/no-regex-spaces": "error", + "eslint/no-return-await": "error", + "eslint/no-script-url": "error", + "eslint/no-self-assign": "error", + "eslint/no-self-compare": "error", + "eslint/no-setter-return": "error", + "eslint/no-shadow-restricted-names": "error", + "eslint/no-sparse-arrays": "error", + "eslint/no-template-curly-in-string": "error", "eslint/no-ternary": "off", + "eslint/no-this-before-super": "error", + "eslint/no-undef": "off", "eslint/no-undefined": "off", + "eslint/no-unsafe-finally": "error", + "eslint/no-unsafe-negation": "error", + "eslint/no-unsafe-optional-chaining": "error", + "eslint/no-unused-labels": "error", + "eslint/no-unused-private-class-members": "error", "eslint/sort-keys": "off", + "eslint/react-in-jsx-scope": "off", "eslint/no-unused-vars": [ "error", { "ignoreRestSiblings": true } ], + "eslint/no-useless-catch": "error", + "eslint/no-useless-escape": "error", + "eslint/no-useless-rename": "error", + "eslint/no-var": "error", + "eslint/no-void": "error", + "eslint/no-with": "error", + "eslint/radix": "error", "eslint/require-await": "off", + "eslint/require-yield": "error", "eslint/sort-imports": [ "off", { @@ -66,69 +218,146 @@ "memberSyntaxSortOrder": ["single", "multiple", "all", "none"] } ], - "eslint/yoda": "error", + "eslint/unicode-bom": "error", + "eslint/use-isnan": "error", + "eslint/valid-typeof": "error", + "eslint/init-declarations": "off", + "eslint/func-style": "off", "eslint/max-lines-per-function": "off", "eslint/max-nested-callbacks": "off", "eslint/max-depth": "off", - "eslint/init-declarations": "off", - "eslint/curly": "off", - - "import/no-namespace": "off", - "import/max-dependencies": "off", - "import/namespace": "off", - "import/no-default-export": "off", - "import/no-duplicates": "off", - "import/unambiguous": "off", - "import/exports-last": "off", - "import/no-anonymous-default-export": "off", - "import/group-exports": "off", + "oxc/bad-bitwise-operator": "error", + "oxc/no-accumulating-spread": "off", + "oxc/no-async-await": "off", + "oxc/no-barrel-file": "off", + "oxc/no-const-enum": "error", + "oxc/no-optional-chaining": "off", + "oxc/no-rest-spread-properties": "off", "react-perf/jsx-no-jsx-as-prop": "off", "react-perf/jsx-no-new-array-as-prop": "off", "react-perf/jsx-no-new-function-as-prop": "off", "react-perf/jsx-no-new-object-as-prop": "off", - "react/jsx-no-useless-fragment": "off", - "react/iframe-missing-sandbox": "error", - "react/jsx-no-target-blank": "off", - "react/react-in-jsx-scope": "off", - "react/no-array-index-key": "off", + "react_perf/jsx-no-jsx-as-prop": "error", + "react_perf/jsx-no-new-array-as-prop": "error", + "react_perf/jsx-no-new-function-as-props": "error", + "react_perf/jsx-no-new-object-as-prop": "error", + "react/button-has-type": "error", + "react/exhaustive-deps": "error", "react/jsx-filename-extension": [ "error", - { "extensions": [".jsx", ".tsx"] } + { + "extensions": [".jsx", ".tsx"] + } ], + "react/iframe-missing-sandbox": "error", + "react/jsx-key": "error", + "react/jsx-no-comment-text-nodes": "error", + "react/jsx-no-duplicate-props": "error", + "react/jsx-no-target-blank": "off", + "react/jsx-no-undef": "error", + "react/jsx-no-useless-fragment": "off", + "react/no-children-prop": "error", + "react/no-dangerously-set-inner-html": "error", + "react/no-direct-mutation-state": "error", + "react/no-find-dom-node": "error", + "react/no-is-mounted": "error", + "react/no-render-return-value": "error", + "react/no-set-state": "off", + "react/no-string-refs": "error", + "react/no-unescaped-entities": "error", + "react/no-unknown-property": "error", + "react/react-in-jsx-scope": "off", + "react/require-render-return": "error", "react/no-danger": "off", + "unicorn/no-instanceof-builtins": "error", + "unicorn/prefer-array-index-of": "off", + "unicorn/prefer-array-find": "off", + "unicorn/no-for-loop": "off", + "unicorn/prefer-object-from-entries": "off", + "unicorn/prefer-global-this": "off", + "unicorn/catch-error-name": "error", + "unicorn/empty-brace-spaces": "error", "unicorn/error-message": "off", + "unicorn/escape-case": "error", + "unicorn/explicit-length-check": "error", "unicorn/filename-case": "off", + "unicorn/new-for-builtins": "error", + "unicorn/no-abusive-eslint-disable": "error", + "unicorn/no-anonymous-default-export": "off", "unicorn/no-array-for-each": "off", "unicorn/no-array-reduce": "off", "unicorn/no-await-expression-member": "off", "unicorn/no-await-in-promise-methods": "off", - "unicorn/no-lonely-if": "off", "unicorn/prefer-set-has": "off", + "unicorn/no-console-spaces": "error", + "unicorn/no-document-cookie": "off", + "unicorn/no-empty-file": "error", + "unicorn/no-hex-escape": "error", + "unicorn/no-instanceof-array": "error", "unicorn/no-invalid-remove-event-listener": "off", + "unicorn/no-lonely-if": "error", + "unicorn/no-magic-array-flat-depth": "off", "unicorn/no-negated-condition": "off", + "unicorn/no-nested-ternary": "error", "unicorn/no-new-array": "off", + "unicorn/no-new-buffer": "error", "unicorn/no-null": "off", "unicorn/no-object-as-default-parameter": "off", "unicorn/no-process-exit": "off", "unicorn/no-single-promise-in-promise-methods": "off", + "unicorn/no-static-only-class": "error", + "unicorn/no-thenable": "error", + "unicorn/no-this-assignment": "error", + "unicorn/no-typeof-undefined": "error", + "unicorn/no-unnecessary-await": "error", + "unicorn/no-unreadable-array-destructuring": "error", + "unicorn/no-unreadable-iife": "error", + "unicorn/no-useless-fallback-in-spread": "error", + "unicorn/no-useless-length-check": "error", "unicorn/no-useless-promise-resolve-reject": "off", + "unicorn/no-useless-spread": "error", + "unicorn/no-useless-switch-case": "error", "unicorn/no-useless-undefined": "off", "unicorn/no-zero-fractions": "off", "unicorn/number-literal-case": "off", "unicorn/numeric-separators-style": "off", "unicorn/prefer-add-event-listener": "off", + "unicorn/prefer-array-flat": "error", + "unicorn/prefer-array-flat-map": "error", "unicorn/prefer-array-some": "off", "unicorn/prefer-blob-reading-methods": "off", "unicorn/prefer-code-point": "off", + "unicorn/prefer-date-now": "error", "unicorn/prefer-dom-node-append": "off", + "unicorn/prefer-dom-node-dataset": "error", "unicorn/prefer-dom-node-remove": "off", - "unicorn/prefer-object-from-entries": "off", + "unicorn/prefer-dom-node-text-content": "error", + "unicorn/prefer-event-target": "error", + "unicorn/prefer-includes": "error", "unicorn/prefer-logical-operator-over-ternary": "off", + "unicorn/prefer-math-trunc": "error", + "unicorn/prefer-modern-dom-apis": "error", + "unicorn/prefer-modern-math-apis": "error", + "unicorn/prefer-native-coercion-functions": "error", "unicorn/prefer-node-protocol": "off", + "unicorn/prefer-number-properties": "error", + "unicorn/prefer-optional-catch-binding": "error", + "unicorn/prefer-prototype-methods": "error", "unicorn/prefer-query-selector": "off", + "unicorn/prefer-reflect-apply": "error", + "unicorn/prefer-regexp-test": "error", + "unicorn/prefer-set-size": "error", + "unicorn/prefer-spread": "error", "unicorn/prefer-string-replace-all": "off", "unicorn/prefer-string-slice": "off", - "unicorn/prefer-global-this": "off" + "unicorn/prefer-string-starts-ends-with": "error", + "unicorn/prefer-string-trim-start-end": "error", + "unicorn/prefer-type-error": "error", + "unicorn/require-array-join-separator": "error", + "unicorn/require-number-to-fixed-digits-argument": "error", + "unicorn/switch-case-braces": "error", + "unicorn/text-encoding-identifier-case": "error", + "unicorn/throw-new-error": "error" }, "settings": { "jsx-a11y": { diff --git a/.storybook/components/DocsContainer.tsx b/.storybook/components/DocsContainer.tsx index 73e3649613..71339cf53e 100644 --- a/.storybook/components/DocsContainer.tsx +++ b/.storybook/components/DocsContainer.tsx @@ -1,11 +1,13 @@ import { Global, ThemeProvider } from '@emotion/react' +import type { + DocsContainerProps as BaseContainerProps} from '@storybook/addon-docs/blocks'; import { DocsContainer as BaseContainer, - DocsContainerProps as BaseContainerProps, Unstyled, } from '@storybook/addon-docs/blocks' import { consoleLightTheme as lightTheme } from '@ultraviolet/themes' -import { ReactNode, cloneElement, isValidElement, useState } from 'react' +import type { ReactNode } from 'react' +import { cloneElement, isValidElement, useState } from 'react' import { globalStyles } from './globalStyle' import '@ultraviolet/fonts/fonts.css' import { GlobalAlert } from '@ultraviolet/ui' diff --git a/examples/next/package.json b/examples/next/package.json index 8d139a2b93..24ca987dd7 100644 --- a/examples/next/package.json +++ b/examples/next/package.json @@ -10,7 +10,7 @@ "private": true, "scripts": { "dev": "next dev", - "build:example": "next build", + "build": "next build", "export": "next export", "start": "next start" }, diff --git a/examples/next/src/components/Link.tsx b/examples/next/src/components/Link.tsx index e8ea22da64..10cf5a9ab7 100644 --- a/examples/next/src/components/Link.tsx +++ b/examples/next/src/components/Link.tsx @@ -20,26 +20,19 @@ export const Link = forwardRef( ...uvprops }, ref, - ) => { - return ( - - - - ) - }, + ) => ( + + + + ), ) export default Link diff --git a/examples/next/src/pages/login/index.tsx b/examples/next/src/pages/login/index.tsx index 0253fed5c9..0c967cbe7d 100644 --- a/examples/next/src/pages/login/index.tsx +++ b/examples/next/src/pages/login/index.tsx @@ -14,12 +14,14 @@ const StyledPage = styled(Stack)` const Content = (props: { tab: string }) => { let tabLoaded = undefined switch (props.tab) { - case 'login': + case 'login': { tabLoaded = break + } - default: + default: { tabLoaded = + } } return tabLoaded } diff --git a/examples/next/src/pages/login/login.tsx b/examples/next/src/pages/login/login.tsx index 620b531143..84d7faf31d 100644 --- a/examples/next/src/pages/login/login.tsx +++ b/examples/next/src/pages/login/login.tsx @@ -4,7 +4,7 @@ import { CheckboxField, Form, Submit, - TextInputFieldV2, + TextInputField, useForm, useWatch, } from '@ultraviolet/form' @@ -25,7 +25,7 @@ const StyledLoginContainer = styled(Stack)` padding: ${({ theme }) => theme.space['4']}; ` -const StyledInput = styled(TextInputFieldV2)` +const StyledInput = styled(TextInputField)` padding: ${({ theme }) => theme.space['1.5']} ${({ theme }) => theme.space['5']}; width: 100%; diff --git a/examples/next/src/pages/login/signup.tsx b/examples/next/src/pages/login/signup.tsx index cddfc24a0d..0365ae7394 100644 --- a/examples/next/src/pages/login/signup.tsx +++ b/examples/next/src/pages/login/signup.tsx @@ -4,7 +4,7 @@ import { Form, RadioGroupField, Submit, - TextInputFieldV2, + TextInputField, useForm, useWatch, } from '@ultraviolet/form' @@ -28,7 +28,7 @@ const StyledSignUpContainer = styled(Stack)` padding: ${({ theme }) => theme.space['4']}; ` -const StyledInput = styled(TextInputFieldV2)` +const StyledInput = styled(TextInputField)` padding: ${({ theme }) => theme.space['1.5']} ${({ theme }) => theme.space['0']}; width: 100%; @@ -100,8 +100,8 @@ const SignUp = () => { - - + + { const [count, setCount] = useState(0) return ( - <> - - - - Classic - - - - - - - Count:{count} - - - Alert - - + + + + Classic + + + + + + + Count:{count} + + + Alert + ) } diff --git a/package.json b/package.json index d9c3347c53..0307966daf 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "emoji-toolkit": "9.0.1", "esbuild-plugin-browserslist": "1.0.1", "eslint": "9.31.0", - "eslint-plugin-oxlint": "0.18.1", + "eslint-plugin-oxlint": "1.6.0", "eslint-plugin-storybook": "9.0.18", "eslint-plugin-testing-library": "7.5.3", "expect": "30.0.5", @@ -160,7 +160,7 @@ "identity-obj-proxy": "3.0.0", "jest-axe": "10.0.0", "lint-staged": "16.1.2", - "oxlint": "0.18.1", + "oxlint": "1.6.0", "postcss": "8.5.6", "publint": "0.3.12", "react": "19.1.1", diff --git a/packages/form/src/components/DateInputField/index.tsx b/packages/form/src/components/DateInputField/index.tsx index 0300ff2dde..7f973dc436 100644 --- a/packages/form/src/components/DateInputField/index.tsx +++ b/packages/form/src/components/DateInputField/index.tsx @@ -74,7 +74,9 @@ export const DateInputField = < format={ format || (value => { - if (!value) return '' + if (!value) { + return '' + } const date = parseDate(value) return showMonthYearPicker diff --git a/packages/form/src/components/SelectInputField/__tests__/__snapshots__/index.test.tsx.snap b/packages/form/src/components/SelectInputField/__tests__/__snapshots__/index.test.tsx.snap index 12f9fe2ba8..74632fecfa 100644 --- a/packages/form/src/components/SelectInputField/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/form/src/components/SelectInputField/__tests__/__snapshots__/index.test.tsx.snap @@ -510,8 +510,8 @@ exports[`SelectInputField > should display right value on grouped options 1`] = class="emotion-2 emotion-3" >
should display right value on grouped options 1`] = class="emotion-6 emotion-7" >
should display right value on grouped options 1`] = data-size="large" data-state="neutral" data-testid="select-input-test" - id="«rg»" + id="«rk»" role="combobox" tabindex="0" > @@ -560,7 +560,7 @@ exports[`SelectInputField > should display right value on grouped options 1`] = class="emotion-17 emotion-18 emotion-19" data-animated="false" data-has-arrow="false" - id="«rh»" + id="«rl»" role="dialog" style="opacity: 1;" > @@ -1098,8 +1098,8 @@ exports[`SelectInputField > should render correctly 1`] = ` class="emotion-6 emotion-7" >