diff --git a/.github/workflows/verify-js.yml b/.github/workflows/verify-js.yml index edabb44..2b9b43d 100644 --- a/.github/workflows/verify-js.yml +++ b/.github/workflows/verify-js.yml @@ -25,7 +25,7 @@ jobs: pnpm add tailwindcss -w git restore . - name: Format - run: pnpm prettier --ignore-path .gitignore --check "**/*.{js,cjs,mjs,jsx,ts,tsx,css,scss,html,json,md,yml,yaml}" + run: pnpm prettier --ignore-path .gitignore --check "**/*.{css,scss,html,json,md,mdx,yml,yaml}" lint-js: name: Lint JS diff --git a/examples/hatchet/typescript-connectors/connectors/dropbox.ts b/examples/hatchet/typescript-connectors/connectors/dropbox.ts index 9ccb907..e324657 100644 --- a/examples/hatchet/typescript-connectors/connectors/dropbox.ts +++ b/examples/hatchet/typescript-connectors/connectors/dropbox.ts @@ -58,7 +58,7 @@ const listFolder = dropbox.task({ method: 'POST', headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${token.access_token}`, + 'Authorization': `Bearer ${token.access_token}`, }, body: JSON.stringify({ path: '', @@ -82,7 +82,7 @@ const listFolder = dropbox.task({ method: 'POST', headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${token.access_token}`, + 'Authorization': `Bearer ${token.access_token}`, }, body: JSON.stringify({ cursor, @@ -113,7 +113,7 @@ const enrichEntries = dropbox.task({ const token = await ctx.parentOutput(getAccessToken); const { entries } = await ctx.parentOutput(listFolder); - const paperFiles = entries.filter((f) => f.name.endsWith('.paper')); + const paperFiles = entries.filter(f => f.name.endsWith('.paper')); if (paperFiles.length === 0) return entries; ctx.logger.info(`Retrieving metadata for ${paperFiles.length} files.`); @@ -121,10 +121,10 @@ const enrichEntries = dropbox.task({ method: 'POST', headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${token.access_token}`, + 'Authorization': `Bearer ${token.access_token}`, }, body: JSON.stringify({ - files: paperFiles.map((f) => f.path_lower), + files: paperFiles.map(f => f.path_lower), }), }); @@ -159,7 +159,7 @@ dropbox.task({ const token = await ctx.parentOutput(getAccessToken); const { entries } = await ctx.parentOutput(enrichEntries); - const paperFiles = entries.filter((f) => f.name.endsWith('.paper')); + const paperFiles = entries.filter(f => f.name.endsWith('.paper')); if (paperFiles.length === 0) return; for (let i = 0; i < paperFiles.length; i++) { @@ -169,7 +169,7 @@ dropbox.task({ const response = await fetch(`https://content.dropboxapi.com/2/files/export`, { method: 'POST', headers: { - Authorization: `Bearer ${token.access_token}`, + 'Authorization': `Bearer ${token.access_token}`, 'Dropbox-API-Arg': JSON.stringify({ path: file.path_lower, export_format: 'markdown', diff --git a/examples/node/basics/fs.ts b/examples/node/basics/fs.ts index c216579..504cf78 100644 --- a/examples/node/basics/fs.ts +++ b/examples/node/basics/fs.ts @@ -18,9 +18,9 @@ async function main() { const [u2] = await measure(usingReadStream); const [u3] = await measure(usingSharedBuffer); - const t1 = u1.map((u) => u.arrayBuffers / 1_000_000); - const t2 = u2.map((u) => u.arrayBuffers / 1_000_000); - const t3 = u3.map((u) => u.arrayBuffers / 1_000_000); + const t1 = u1.map(u => u.arrayBuffers / 1_000_000); + const t2 = u2.map(u => u.arrayBuffers / 1_000_000); + const t3 = u3.map(u => u.arrayBuffers / 1_000_000); console.log( asciichart.plot([t1, t2, t3], { diff --git a/examples/react/server-rendering/scripts/bench.ts b/examples/react/server-rendering/scripts/bench.ts index 3aa50ab..5b2d92a 100644 --- a/examples/react/server-rendering/scripts/bench.ts +++ b/examples/react/server-rendering/scripts/bench.ts @@ -7,11 +7,11 @@ export const options = { }; const urls = { - vite: 'http://127.0.0.1:3000', + 'vite': 'http://127.0.0.1:3000', 'vite-stream': 'http://127.0.0.1:3000', 'next-pages': 'http://127.0.0.1:3000', 'next-app': 'http://127.0.0.1:3000/app', - tss: 'http://127.0.0.1:3000', + 'tss': 'http://127.0.0.1:3000', }; export default function bench() { diff --git a/examples/react/server-rendering/vite/server-stream.ts b/examples/react/server-rendering/vite/server-stream.ts index 21ca038..542535a 100644 --- a/examples/react/server-rendering/vite/server-stream.ts +++ b/examples/react/server-rendering/vite/server-stream.ts @@ -33,7 +33,7 @@ server.on('request', async function (req, res) { let renderStream; if (isDevelopment) { - await new Promise((resolve) => vite.middlewares(req, res, resolve)); + await new Promise(resolve => vite.middlewares(req, res, resolve)); template = await fs.readFile(path.resolve(import.meta.dirname, 'index.html'), 'utf8'); template = await vite.transformIndexHtml(url, template); diff --git a/examples/react/server-rendering/vite/server.ts b/examples/react/server-rendering/vite/server.ts index 6e243e0..655c997 100644 --- a/examples/react/server-rendering/vite/server.ts +++ b/examples/react/server-rendering/vite/server.ts @@ -31,7 +31,7 @@ server.on('request', async function (req, res) { let render; if (isDevelopment) { - await new Promise((resolve) => vite.middlewares(req, res, resolve)); + await new Promise(resolve => vite.middlewares(req, res, resolve)); template = await fs.readFile(path.resolve(import.meta.dirname, 'index.html'), 'utf8'); template = await vite.transformIndexHtml(url, template); diff --git a/examples/tanstack/start-solid/babel.config.js b/examples/tanstack/start-solid/babel.config.js index 7f2c302..dff0f2e 100644 --- a/examples/tanstack/start-solid/babel.config.js +++ b/examples/tanstack/start-solid/babel.config.js @@ -3,15 +3,10 @@ export default function babel(api) { return { plugins: [ - [ - '@stylexjs/babel-plugin', - { - debug: process.env.NODE_ENV === 'development', - unstable_moduleResolution: { - type: 'commonJS', - }, - }, - ], + ['@stylexjs/babel-plugin', { + debug: process.env.NODE_ENV === 'development', + unstable_moduleResolution: { type: 'commonJS' }, + }], ], parserOpts: { plugins: ['jsx', 'typescript'], diff --git a/examples/tanstack/start-solid/postcss.config.js b/examples/tanstack/start-solid/postcss.config.js index 6cb2ac9..59240b9 100644 --- a/examples/tanstack/start-solid/postcss.config.js +++ b/examples/tanstack/start-solid/postcss.config.js @@ -1,4 +1,3 @@ -/* eslint-disable import-x/no-extraneous-dependencies */ import stylex from '@stylexjs/postcss-plugin'; import autoprefixer from 'autoprefixer'; diff --git a/examples/tanstack/start-solid/src/StaleClosures.tsx b/examples/tanstack/start-solid/src/StaleClosures.tsx index 206bf6a..7cc3077 100644 --- a/examples/tanstack/start-solid/src/StaleClosures.tsx +++ b/examples/tanstack/start-solid/src/StaleClosures.tsx @@ -44,7 +44,7 @@ function Signals() {
Timed Log:
Log:
-
@@ -133,7 +133,7 @@ function RefSync() { }, []); const handleIncrement = useCallback(() => { - setCount((prev) => prev + 1); + setCount(prev => prev + 1); countRef.current += 1; }, []); @@ -205,7 +205,7 @@ function useStateRef(value: T): [React.RefObject, (newState: T) => void] { if (Object.is(ref.current, newState)) return; ref.current = newState; - forceRender((prev) => !prev); + forceRender(prev => !prev); } return [ref, setState]; diff --git a/examples/tanstack/start/src/TransitionRedux.tsx b/examples/tanstack/start/src/TransitionRedux.tsx index e414ba8..ee16daa 100644 --- a/examples/tanstack/start/src/TransitionRedux.tsx +++ b/examples/tanstack/start/src/TransitionRedux.tsx @@ -31,7 +31,7 @@ function TransitionRedux() { } function SettingsPanel() { - const page = useAppSelector((state) => state.posts.page); + const page = useAppSelector(state => state.posts.page); const dispatch = useAppDispatch(); @@ -57,7 +57,7 @@ function SettingsPanel() { } const Posts = function Posts() { - const page = useAppSelector((state) => state.posts.page_slow); + const page = useAppSelector(state => state.posts.page_slow); return (
diff --git a/examples/tanstack/start/src/TransitionUseContextSelector.tsx b/examples/tanstack/start/src/TransitionUseContextSelector.tsx index 4cf8c59..cece5ec 100644 --- a/examples/tanstack/start/src/TransitionUseContextSelector.tsx +++ b/examples/tanstack/start/src/TransitionUseContextSelector.tsx @@ -25,20 +25,20 @@ function TransitionUseContextSelector() { } function SettingsPanel() { - const page = useContextSelector(Context, (v) => v.page); - const set_page = useContextSelector(Context, (v) => v.set_page); - const set_page_slow = useContextSelector(Context, (v) => v.set_page_slow); + const page = useContextSelector(Context, v => v.page); + const set_page = useContextSelector(Context, v => v.set_page); + const set_page_slow = useContextSelector(Context, v => v.set_page_slow); const update = useContextUpdate(Context); const [is_pending, start_transition] = useTransition(); const handle_click = () => { - set_page((prev) => prev + 1); + set_page(prev => prev + 1); start_transition(() => { update(() => { - set_page_slow((prev) => prev + 1); + set_page_slow(prev => prev + 1); }); }); }; @@ -55,7 +55,7 @@ function SettingsPanel() { } const Posts = function Posts() { - const page = useContextSelector(Context, (v) => v.page_slow); + const page = useContextSelector(Context, v => v.page_slow); return (
diff --git a/examples/tanstack/start/src/TransitionUseSearch.tsx b/examples/tanstack/start/src/TransitionUseSearch.tsx index 319dde7..48d0318 100644 --- a/examples/tanstack/start/src/TransitionUseSearch.tsx +++ b/examples/tanstack/start/src/TransitionUseSearch.tsx @@ -26,11 +26,11 @@ function TransitionSearch() { const handle_click = () => { navigate({ - search: (prev) => ({ page: (Number(prev.page) + 1).toString() }), + search: prev => ({ page: (Number(prev.page) + 1).toString() }), }); start_transition(() => { - set_page_slow((prev) => (prev ? prev + 1 : 1)); + set_page_slow(prev => (prev ? prev + 1 : 1)); }); }; diff --git a/examples/tanstack/start/src/TransitionUseState.tsx b/examples/tanstack/start/src/TransitionUseState.tsx index f4645d4..379955d 100644 --- a/examples/tanstack/start/src/TransitionUseState.tsx +++ b/examples/tanstack/start/src/TransitionUseState.tsx @@ -18,10 +18,10 @@ function TransitionUseState() { const [is_pending, start_transition] = useTransition(); const handle_click = () => { - set_page((prev) => prev + 1); + set_page(prev => prev + 1); start_transition(() => { - set_page_slow((prev) => prev + 1); + set_page_slow(prev => prev + 1); }); }; diff --git a/examples/tanstack/start/src/TransitionZustand.tsx b/examples/tanstack/start/src/TransitionZustand.tsx index 6a68359..78fe8f2 100644 --- a/examples/tanstack/start/src/TransitionZustand.tsx +++ b/examples/tanstack/start/src/TransitionZustand.tsx @@ -29,9 +29,9 @@ interface SettingsPanelProps { } function SettingsPanel({ store }: SettingsPanelProps) { - const page = store((state) => state.page); - const set_page = store((state) => state.set_page); - const set_page_slow = store((state) => state.set_page_slow); + const page = store(state => state.page); + const set_page = store(state => state.set_page); + const set_page_slow = store(state => state.set_page_slow); const [is_pending, start_transition] = useTransition(); @@ -59,7 +59,7 @@ interface PostsProps { } const Posts = function Posts({ store }: PostsProps) { - const page = store((state) => state.page_slow); + const page = store(state => state.page_slow); return (
@@ -90,10 +90,10 @@ interface State { } const create_store = () => { - return create((set) => ({ + return create(set => ({ page: 1, page_slow: 1, - set_page: () => set((state) => ({ page: state.page + 1 })), - set_page_slow: () => set((state) => ({ page_slow: state.page_slow + 1 })), + set_page: () => set(state => ({ page: state.page + 1 })), + set_page_slow: () => set(state => ({ page_slow: state.page_slow + 1 })), })); }; diff --git a/examples/tanstack/start/src/external-stores/Redux.tsx b/examples/tanstack/start/src/external-stores/Redux.tsx index 88bf198..d7e70f8 100644 --- a/examples/tanstack/start/src/external-stores/Redux.tsx +++ b/examples/tanstack/start/src/external-stores/Redux.tsx @@ -26,8 +26,8 @@ function Redux() { function Counter() { const dispatch = useAppDispatch(); - const loading = useAppSelector((state) => state.counter.loading); - const count = useAppSelector((state) => state.counter.value); + const loading = useAppSelector(state => state.counter.loading); + const count = useAppSelector(state => state.counter.value); return (
@@ -85,7 +85,7 @@ function decrement(): CounterAction { function increment_async() { return async (dispatch: AppDispatch) => { - await new Promise((resolve) => setTimeout(resolve, 500)); + await new Promise(resolve => setTimeout(resolve, 500)); dispatch(increment_by_amount(2)); }; } @@ -96,7 +96,7 @@ function increment_async_a() { dispatch(increment_by_amount(1)); try { - await new Promise((resolve) => setTimeout(resolve, 500)); + await new Promise(resolve => setTimeout(resolve, 500)); dispatch({ type: INCREMENT_FULFILLED, payload: 1 }); } catch { dispatch({ type: INCREMENT_REJECTED }); diff --git a/examples/tanstack/start/src/external-stores/ReduxToolkit.tsx b/examples/tanstack/start/src/external-stores/ReduxToolkit.tsx index 30475b6..06fa417 100644 --- a/examples/tanstack/start/src/external-stores/ReduxToolkit.tsx +++ b/examples/tanstack/start/src/external-stores/ReduxToolkit.tsx @@ -25,8 +25,8 @@ function ReduxToolkit() { function Counter() { const dispatch = useAppDispatch(); - const loading = useAppSelector((state) => state.counter.loading); - const count = useAppSelector((state) => state.counter.value); + const loading = useAppSelector(state => state.counter.loading); + const count = useAppSelector(state => state.counter.value); return (
@@ -96,14 +96,14 @@ const { increment, increment_by_amount } = counter_slice.actions; function increment_async() { return async (dispatch: AppDispatch) => { - await new Promise((resolve) => setTimeout(resolve, 500)); + await new Promise(resolve => setTimeout(resolve, 500)); dispatch(increment_by_amount(2)); }; } const increment_async_a = createAsyncThunk('counter/increment_async_a', async (_, thunk) => { thunk.dispatch(increment_by_amount(1)); - await new Promise((resolve) => setTimeout(resolve, 500)); + await new Promise(resolve => setTimeout(resolve, 500)); return 1; }); diff --git a/examples/tanstack/start/src/external-stores/Zustand.tsx b/examples/tanstack/start/src/external-stores/Zustand.tsx index 3700102..d8ad981 100644 --- a/examples/tanstack/start/src/external-stores/Zustand.tsx +++ b/examples/tanstack/start/src/external-stores/Zustand.tsx @@ -22,14 +22,14 @@ interface CounterProps { } function Counter({ store }: CounterProps) { - const increment = store((state) => state.increment); - const decrement = store((state) => state.decrement); - const increment_async = store((state) => state.increment_async); - const increment_async_a = store((state) => state.increment_async_a); - const increment_async_b = store((state) => state.increment_async_b); + const increment = store(state => state.increment); + const decrement = store(state => state.decrement); + const increment_async = store(state => state.increment_async); + const increment_async_a = store(state => state.increment_async_a); + const increment_async_b = store(state => state.increment_async_b); - const loading = store((state) => state.loading); - const count = store((state) => state.value); + const loading = store(state => state.loading); + const count = store(state => state.value); return (
@@ -71,19 +71,19 @@ interface CounterSlice { const counter_slice: StateCreator = (set, get) => ({ loading: false, value: 0, - increment: () => set((state) => ({ value: state.value + 1 })), - decrement: () => set((state) => ({ value: state.value - 1 })), - increment_by_amount: (value: number) => set((state) => ({ value: state.value + value })), + increment: () => set(state => ({ value: state.value + 1 })), + decrement: () => set(state => ({ value: state.value - 1 })), + increment_by_amount: (value: number) => set(state => ({ value: state.value + value })), increment_async: async () => { - await new Promise((resolve) => setTimeout(resolve, 500)); + await new Promise(resolve => setTimeout(resolve, 500)); get().increment_by_amount(2); }, increment_async_a: async () => { set({ loading: true }); get().increment_by_amount(1); - await new Promise((resolve) => setTimeout(resolve, 500)); - set((state) => ({ loading: false, value: state.value + 1 })); + await new Promise(resolve => setTimeout(resolve, 500)); + set(state => ({ loading: false, value: state.value + 1 })); }, increment_async_b: async () => { set({ loading: true }); diff --git a/examples/webpack/typescript-fastify/mods/handlers.ts b/examples/webpack/typescript-fastify/mods/handlers.ts index 728bcdd..e7065d9 100644 --- a/examples/webpack/typescript-fastify/mods/handlers.ts +++ b/examples/webpack/typescript-fastify/mods/handlers.ts @@ -65,4 +65,4 @@ export async function bcryptHash(request: FastifyRequest, reply: FastifyReply) { reply.send({ hash }); } -const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); +const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); diff --git a/examples/webpack/typescript-fastify/rspack.config.ts b/examples/webpack/typescript-fastify/rspack.config.ts index ab0ba91..40c8870 100644 --- a/examples/webpack/typescript-fastify/rspack.config.ts +++ b/examples/webpack/typescript-fastify/rspack.config.ts @@ -1,4 +1,3 @@ -/* eslint-disable import-x/no-extraneous-dependencies */ import path from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -11,13 +10,13 @@ const mode = process.env.NODE_ENV === 'production' ? 'production' : 'development const ignoredPackages = { 'aws-sdk': true, 'mock-aws-s3': true, - nock: true, + 'nock': true, }; const customConfig = { plugins: [ new rspack.IgnorePlugin({ - checkResource: (resource) => !!ignoredPackages[resource], + checkResource: resource => !!ignoredPackages[resource], }), ], }; diff --git a/packages/config/eslint.js b/packages/config/eslint.js index c2e6c6d..cf9f87f 100755 --- a/packages/config/eslint.js +++ b/packages/config/eslint.js @@ -1,8 +1,9 @@ import stylex_plugin from '@stylexjs/eslint-plugin'; +import stylistic_plugin from '@stylistic/eslint-plugin'; import { defineConfig } from 'eslint/config'; import gitignore from 'eslint-config-flat-gitignore'; -import prettier_config from 'eslint-config-prettier/flat'; import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript'; +import tailwind_plugin from 'eslint-plugin-better-tailwindcss'; import compat_plugin from 'eslint-plugin-compat'; import * as imp from 'eslint-plugin-import-x'; import jsx_a11y_plugin from 'eslint-plugin-jsx-a11y'; @@ -50,38 +51,34 @@ function import_x() { // 'error', // { js: 'ignorePackages', jsx: 'never', ts: 'ignorePackages', tsx: 'never' }, // ], - 'import-x/no-extraneous-dependencies': [ - 'error', - { - devDependencies: [ - '**/commitlint.config.*s', - '**/eslint.config.*s', - '**/lint-staged.config.*s', - '**/prettier.config.*s', - '**/rspack.config.*s', - '**/stylelint.config.*s', - '**/vite.config.*s', - '**/vitest.config.*s', - '**/webpack.config.*s', - ], - }, - ], + 'import-x/no-extraneous-dependencies': ['error', { + devDependencies: [ + '**/babel.config.*s', + '**/commitlint.config.*s', + '**/eslint.config.*s', + '**/lint-staged.config.*s', + '**/postcss.config.*s', + '**/prettier.config.*s', + '**/rspack.config.*s', + '**/stylelint.config.*s', + '**/vite.config.*s', + '**/vitest.config.*s', + '**/webpack.config.*s', + ], + }], 'import-x/no-unresolved': ['error', { ignore: [String.raw`^@\/build`] }], // x - 'import-x/order': [ - 'error', - { - alphabetize: { order: 'asc' }, - groups: getImportGroups(), - pathGroups: [ - { - pattern: '@/**', - group: 'internal', - }, - ], - pathGroupsExcludedImportTypes: ['type'], - 'newlines-between': 'always', - }, - ], + 'import-x/order': ['error', { + 'alphabetize': { order: 'asc' }, + 'groups': getImportGroups(), + 'pathGroups': [ + { + pattern: '@/**', + group: 'internal', + }, + ], + 'pathGroupsExcludedImportTypes': ['type'], + 'newlines-between': 'always', + }], }, settings: { 'import-x/resolver-next': [createTypeScriptImportResolver()], @@ -107,7 +104,7 @@ function typescript() { function react() { return { name: 'react/recommended', - files: ['**/*.{js,jsx,ts,tsx}'], + files: ['**/*.{jsx,tsx}'], extends: [react_plugin.configs.flat['jsx-runtime']], languageOptions: { globals: { ...globals.browser, ...globals.serviceworker }, @@ -119,7 +116,7 @@ function react() { 'react/prop-types': 'error', // 'react/jsx-no-leaked-render': 'error', - 'react/require-default-props': ['error', { forbidDefaultForRequired: true, classes: 'ignore', functions: 'ignore' }], // prettier-ignore + 'react/require-default-props': ['error', { forbidDefaultForRequired: true, classes: 'ignore', functions: 'ignore' }], }, }; } @@ -127,7 +124,7 @@ function react() { function react_hooks() { return { name: 'react-hooks/recommended', - files: ['**/*.{js,jsx,ts,tsx}'], + files: ['**/*.{jsx,tsx}'], extends: [react_hooks_plugin.configs.flat['recommended-latest']], }; } @@ -142,80 +139,71 @@ function react_you_might_not_need_an_effect() { function stylex() { return { name: 'stylex/recommended', - files: ['**/*.{js,jsx,ts,tsx}'], + files: ['**/*.{jsx,tsx}'], plugins: { '@stylexjs': stylex_plugin }, rules: { '@stylexjs/no-unused': 'error', - '@stylexjs/sort-keys': [ - 'warn', - { - validImports: ['stylex', '@stylexjs/stylex', { from: 'react-strict-dom', as: 'css' }], - order: 'recess', - }, - ], + '@stylexjs/sort-keys': ['warn', { + validImports: ['stylex', '@stylexjs/stylex', { from: 'react-strict-dom', as: 'css' }], + order: 'recess', + }], '@stylexjs/valid-shorthands': 'warn', '@stylexjs/valid-styles': 'error', }, }; } +function tailwind() { + return { + name: 'better-tailwindcss/recommended', + files: ['**/*.{jsx,tsx}'], + plugins: { 'better-tailwindcss': tailwind_plugin }, + rules: { + 'better-tailwindcss/enforce-consistent-line-wrapping': ['warn', { printWidth: 100, preferSingleLine: true }], + 'better-tailwindcss/enforce-consistent-class-order': 'warn', + 'better-tailwindcss/enforce-canonical-classes': 'warn', + 'better-tailwindcss/no-duplicate-classes': 'warn', + 'better-tailwindcss/no-deprecated-classes': 'warn', + 'better-tailwindcss/no-unnecessary-whitespace': 'warn', + 'better-tailwindcss/no-unknown-classes': 'error', + 'better-tailwindcss/no-conflicting-classes': 'error', + }, + }; +} + function jsx_a11y() { return { name: 'jsx-a11y/recommended', plugins: { 'jsx-a11y': jsx_a11y_plugin }, rules: { 'jsx-a11y/aria-proptypes': 'error', - 'jsx-a11y/interactive-supports-focus': [ - 'error', - { - tabbable: ['button', 'checkbox', 'link', 'searchbox', 'spinbutton', 'switch', 'textbox'], - }, - ], - 'jsx-a11y/no-interactive-element-to-noninteractive-role': [ - 'error', - { - tr: ['none', 'presentation'], - canvas: ['img'], - }, - ], - 'jsx-a11y/no-noninteractive-element-interactions': [ - 'error', - { - handlers: [ - 'onClick', - 'onError', - 'onLoad', - 'onMouseDown', - 'onMouseUp', - 'onKeyPress', - 'onKeyDown', - 'onKeyUp', - ], - alert: ['onKeyUp', 'onKeyDown', 'onKeyPress'], - body: ['onError', 'onLoad'], - dialog: ['onKeyUp', 'onKeyDown', 'onKeyPress'], - iframe: ['onError', 'onLoad'], - img: ['onError', 'onLoad'], - }, - ], - 'jsx-a11y/no-noninteractive-element-to-interactive-role': [ - 'error', - { - ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], - ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], - li: ['menuitem', 'menuitemradio', 'menuitemcheckbox', 'option', 'row', 'tab', 'treeitem'], - table: ['grid'], - td: ['gridcell'], - fieldset: ['radiogroup', 'presentation'], - }, - ], - 'jsx-a11y/no-static-element-interactions': [ - 'error', - { - allowExpressionValues: true, - handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'], - }, - ], + 'jsx-a11y/interactive-supports-focus': ['error', { + tabbable: ['button', 'checkbox', 'link', 'searchbox', 'spinbutton', 'switch', 'textbox'], + }], + 'jsx-a11y/no-interactive-element-to-noninteractive-role': ['error', { + tr: ['none', 'presentation'], + canvas: ['img'], + }], + 'jsx-a11y/no-noninteractive-element-interactions': ['error', { + handlers: ['onClick', 'onError', 'onLoad', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'], + alert: ['onKeyUp', 'onKeyDown', 'onKeyPress'], + body: ['onError', 'onLoad'], + dialog: ['onKeyUp', 'onKeyDown', 'onKeyPress'], + iframe: ['onError', 'onLoad'], + img: ['onError', 'onLoad'], + }], + 'jsx-a11y/no-noninteractive-element-to-interactive-role': ['error', { + ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], + ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], + li: ['menuitem', 'menuitemradio', 'menuitemcheckbox', 'option', 'row', 'tab', 'treeitem'], + table: ['grid'], + td: ['gridcell'], + fieldset: ['radiogroup', 'presentation'], + }], + 'jsx-a11y/no-static-element-interactions': ['error', { + allowExpressionValues: true, + handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'], + }], }, }; } @@ -245,11 +233,34 @@ function unicorn() { }; } -function prettier() { - return { - name: 'prettier/config', - extends: [prettier_config], - }; +function stylistic() { + return [ + stylistic_plugin.configs.customize({ + indent: 2, + quotes: 'single', + semi: true, + jsx: true, + braceStyle: '1tbs', + }), + { + rules: { + '@stylistic/jsx-one-expression-per-line': ['error', { allow: 'non-jsx' }], + '@stylistic/jsx-closing-bracket-location': ['error', { nonEmpty: 'after-props', selfClosing: 'tag-aligned' }], + '@stylistic/jsx-wrap-multilines': ['error', { + declaration: 'parens-new-line', + assignment: 'parens-new-line', + return: 'parens-new-line', + arrow: 'parens-new-line', + condition: 'ignore', + logical: 'ignore', + prop: 'ignore', + propertyValue: 'ignore', + }], + '@stylistic/operator-linebreak': ['error', 'after', { overrides: { '?': 'before', ':': 'before', '|': 'before' } }], + '@stylistic/quotes': ['error', 'single', { allowTemplateLiterals: 'always', avoidEscape: true }], + }, + }, + ]; } function perfectionist() { @@ -260,45 +271,33 @@ function perfectionist() { 'perfectionist/sort-array-includes': 'warn', 'perfectionist/sort-enums': 'warn', 'perfectionist/sort-heritage-clauses': 'warn', - 'perfectionist/sort-interfaces': [ - 'warn', - { - type: 'unsorted', - groups: ['property', 'method'], - }, - ], + 'perfectionist/sort-interfaces': ['warn', { + type: 'unsorted', + groups: ['property', 'method'], + }], 'perfectionist/sort-intersection-types': 'warn', - 'perfectionist/sort-jsx-props': [ - 'warn', - { - groups: ['key', 'ref', 'name', 'content', 'unknown', 'callback'], - customGroups: [ - { groupName: 'key', elementNamePattern: '^key$' }, - { groupName: 'ref', elementNamePattern: '^ref$' }, - { groupName: 'name', elementNamePattern: '^name$' }, - { groupName: 'content', elementNamePattern: '^content$' }, - { groupName: 'callback', elementNamePattern: ['^on_.+', '^on[A-Z].*'] }, - ], - }, - ], + 'perfectionist/sort-jsx-props': ['warn', { + groups: ['key', 'ref', 'name', 'content', 'unknown', 'callback'], + customGroups: [ + { groupName: 'key', elementNamePattern: '^key$' }, + { groupName: 'ref', elementNamePattern: '^ref$' }, + { groupName: 'name', elementNamePattern: '^name$' }, + { groupName: 'content', elementNamePattern: '^content$' }, + { groupName: 'callback', elementNamePattern: ['^on_.+', '^on[A-Z].*'] }, + ], + }], 'perfectionist/sort-maps': 'warn', 'perfectionist/sort-named-exports': 'warn', 'perfectionist/sort-named-imports': 'warn', - 'perfectionist/sort-object-types': [ - 'warn', - { - type: 'unsorted', - groups: ['property', 'method'], - }, - ], + 'perfectionist/sort-object-types': ['warn', { + type: 'unsorted', + groups: ['property', 'method'], + }], 'perfectionist/sort-sets': 'warn', 'perfectionist/sort-switch-case': 'warn', - 'perfectionist/sort-union-types': [ - 'warn', - { - groups: ['unknown', 'named', 'nullish'], - }, - ], + 'perfectionist/sort-union-types': ['warn', { + groups: ['unknown', 'named', 'nullish'], + }], }, settings: { perfectionist: { @@ -325,9 +324,10 @@ export default defineConfig([ react_hooks(), react_you_might_not_need_an_effect(), stylex(), + tailwind(), jsx_a11y(), unicorn(), - prettier(), + stylistic(), perfectionist(), compat(), { @@ -345,7 +345,7 @@ export default defineConfig([ ]); export function defineImportResolver(pkgs, options = {}) { - return pkgs.map((pkg) => ({ + return pkgs.map(pkg => ({ files: [`./${pkg}/**/*`], settings: { 'import-x/resolver-next': [ diff --git a/packages/config/lint-staged.js b/packages/config/lint-staged.js index f8003e3..8bf0328 100644 --- a/packages/config/lint-staged.js +++ b/packages/config/lint-staged.js @@ -7,10 +7,10 @@ export default { 'stylelint --cache --cache-location node_modules/.cache/.stylelintcache --max-warnings 0', ], 'package.json': [ - 'sort-package-json --check', // + 'sort-package-json --check', ], - '*.{js,cjs,mjs,jsx,ts,tsx,json,html,css,scss,md,mdx,yml,yaml}': [ - 'prettier --check', // + '*.{css,scss,html,json,md,mdx,yml,yaml}': [ + 'prettier --check', ], '*.py': [ 'uv run ruff check', diff --git a/packages/config/package.json b/packages/config/package.json index e81dc93..b3b8287 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -3,39 +3,36 @@ "version": "0.0.0", "type": "module", "dependencies": { - "@commitlint/cli": "20.4.0", - "@commitlint/config-conventional": "20.4.0", - "@prettier/plugin-oxc": "0.1.3", + "@commitlint/cli": "20.4.1", + "@commitlint/config-conventional": "20.4.1", "@prettier/plugin-xml": "3.4.2", - "@stylexjs/eslint-plugin": "npm:@cmpx/eslint-plugin-stylex@0.16.5", + "@stylexjs/eslint-plugin": "0.17.5", + "@stylistic/eslint-plugin": "5.8.0", "eslint": "9.39.2", "eslint-config-flat-gitignore": "2.1.0", - "eslint-config-prettier": "10.1.8", "eslint-import-resolver-typescript": "4.4.4", + "eslint-plugin-better-tailwindcss": "4.1.1", "eslint-plugin-compat": "npm:@cmpx/eslint-plugin-compat@6.0.3", "eslint-plugin-import-x": "4.16.1", "eslint-plugin-jsx-a11y": "6.10.2", - "eslint-plugin-perfectionist": "5.4.0", + "eslint-plugin-perfectionist": "5.5.0", "eslint-plugin-react": "7.37.5", "eslint-plugin-react-hooks": "7.0.1", "eslint-plugin-react-you-might-not-need-an-effect": "0.8.5", "eslint-plugin-unicorn": "62.0.0", - "globals": "17.2.0", + "globals": "17.3.0", "lint-staged": "16.2.7", - "oxlint": "1.42.0", + "oxlint": "1.43.0", "postcss-scss": "4.0.9", "postcss-styled-syntax": "0.7.1", "prettier": "3.8.1", - "prettier-plugin-classnames": "0.9.0", "prettier-plugin-java": "2.8.1", - "prettier-plugin-merge": "0.9.0", "prettier-plugin-packagejson": "3.0.0", - "prettier-plugin-tailwindcss": "0.7.2", - "stylelint": "17.1.0", - "stylelint-config-recess-order": "7.6.0", + "stylelint": "17.2.0", + "stylelint-config-recess-order": "7.6.1", "stylelint-config-standard": "40.0.0", "stylelint-order": "7.0.1", - "typescript-eslint": "8.54.0" + "typescript-eslint": "8.55.0" }, "peerDependencies": { "typescript": "^5" diff --git a/packages/config/prettier.js b/packages/config/prettier.js index 2661760..f76b332 100755 --- a/packages/config/prettier.js +++ b/packages/config/prettier.js @@ -4,9 +4,9 @@ export default { // '@prettier/plugin-oxc', '@prettier/plugin-xml', 'prettier-plugin-packagejson', - 'prettier-plugin-tailwindcss', - 'prettier-plugin-classnames', - 'prettier-plugin-merge', + // 'prettier-plugin-tailwindcss', + // 'prettier-plugin-classnames', + // 'prettier-plugin-merge', 'prettier-plugin-java', ], bracketSameLine: true, @@ -15,7 +15,7 @@ export default { singleQuote: true, // xmlWhitespaceSensitivity: 'ignore', - tailwindFunctions: ['clsx', 'cva'], - customFunctions: ['clsx', 'cva'], - endingPosition: 'absolute', + // tailwindFunctions: ['clsx', 'cva'], + // customFunctions: ['clsx', 'cva'], + // endingPosition: 'absolute', }; diff --git a/packages/webpack/plugins.ts b/packages/webpack/plugins.ts index 3a963f1..4decb5b 100644 --- a/packages/webpack/plugins.ts +++ b/packages/webpack/plugins.ts @@ -31,7 +31,7 @@ export class RunScriptPlugin { // find the asset of the first entry file. const entry = compilation.entrypoints.keys().next().value; const assets = compilation.getAssets(); - const asset = assets.find((asset) => asset.name === `${entry}.js`); + const asset = assets.find(asset => asset.name === `${entry}.js`); if (!asset) return; // const { filename } = compiler.options.output; diff --git a/stories/src/GradientBorderCard.stories.tsx b/stories/src/GradientBorderCard.stories.tsx index 198185f..d1b7c5e 100644 --- a/stories/src/GradientBorderCard.stories.tsx +++ b/stories/src/GradientBorderCard.stories.tsx @@ -1,3 +1,4 @@ +/* eslint-disable better-tailwindcss/no-unknown-classes */ import type { Meta, StoryObj } from '@storybook/react-vite'; const meta = { @@ -40,16 +41,19 @@ interface GradientBorderCardProps { function GradientBorderCard({ image }: GradientBorderCardProps) { return (
-
+
+ className=" + mask-clip-[content-box,border-box] pointer-events-none absolute inset-0 rounded-[11px] + bg-[linear-gradient(180deg,rgb(255_255_255/16%),rgb(255_255_255/2%))] + mask-[linear-gradient(#fff_0_0),linear-gradient(#fff_0_0)] mask-exclude p-px + "> +

Gradient Border Card

diff --git a/stories/src/Sidebar.stories.tsx b/stories/src/Sidebar.stories.tsx index 7f67a43..eeda29a 100644 --- a/stories/src/Sidebar.stories.tsx +++ b/stories/src/Sidebar.stories.tsx @@ -34,7 +34,7 @@ function SidebarMaxWidth() { const handleToggle = () => { sidebarRef.current.style.maxWidth = isOpen ? '0' : '300px'; - setIsOpen((prev) => !prev); + setIsOpen(prev => !prev); }; return ( @@ -65,7 +65,7 @@ function SidebarWidth() { sidebarRef.current.style.width = `${width}px`; } - setIsOpen((prev) => !prev); + setIsOpen(prev => !prev); }; const handleToggleRAF = () => { @@ -84,7 +84,7 @@ function SidebarWidth() { }); } - setIsOpen((prev) => !prev); + setIsOpen(prev => !prev); }; const handleTransitionEnd = () => { @@ -104,7 +104,7 @@ function SidebarWidth() { Toggle Sidebar (rAF)

- +
); } @@ -133,7 +133,7 @@ function SidebarAnimationAPI() { sidebarRef.current.animate(keyframes, { duration: 250 }); } - setIsOpen((prev) => !prev); + setIsOpen(prev => !prev); }; return ( @@ -155,7 +155,7 @@ interface SidebarProps { function Sidebar({ ref, type, style, onTransitionEnd }: SidebarProps) { return ( -
+
{Array.from({ length: 5 }).map((_, idx) => (
@@ -167,7 +167,7 @@ function Sidebar({ ref, type, style, onTransitionEnd }: SidebarProps) { } const classes = cva( - 'absolute top-0 right-0 h-full flex-col gap-2 border-l-1 border-l-neutral-200 py-2', + 'absolute top-0 right-0 h-full flex-col gap-2 border-l border-l-neutral-200 py-2', { variants: { type: {