Skip to content

Commit

Permalink
feat: add warp ds eslint config (#238)
Browse files Browse the repository at this point in the history
* feat: add warp-ds eslint-config

* feat: fix lint issues

* feat: add  ts,tsx,jsx files in lint:check and lint

* feat: add .eslintrc to add parser, plugin + extend for typescript, react, warp and prettier + fix linting issues

* feat; adjust comment in attention-helper

* fix: add @serverless-guru/prettier-plugin-import-order devDep

* fix: bump @warp-ds/eslint-config + run pnpm lint

* fix: fix issues with bumping happy-dom that caused tests to fail

* fix: fix broken AttentionTest + add eslint-disable-next-line for TextAreaTest

* revert installing eslint-plugin-prettier + eslint-config-prettier

* fix: bump version to 9

* fix: remove eslint-plugin-import since it is already a peerDep in the @warp-ds/eslint-config
  • Loading branch information
felicia-haggqvist authored May 16, 2024
1 parent 5c7e98c commit d83f799
Show file tree
Hide file tree
Showing 114 changed files with 7,252 additions and 8,957 deletions.
12 changes: 12 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint",
"react-hooks"
],
"extends": [
"@warp-ds",
"plugin:react-hooks/recommended",
"plugin:prettier/recommended"
]
}
21 changes: 21 additions & 0 deletions .github/workflows/lint.pr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Lint

on: [pull_request]

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install pnpm and dependencies
uses: pnpm/action-setup@v2
with:
version: 9
run_install: true
- name: Lint
run: pnpm lint:check
4 changes: 2 additions & 2 deletions @types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
declare module '@warp-ds/icons/react' {
export * from '@warp-ds/icons/dist/types/react'
}
export * from '@warp-ds/icons/dist/types/react';
}
35 changes: 18 additions & 17 deletions build.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import esbuild from "esbuild";
import { glob } from "glob";
import fs from 'fs';

import esbuild from 'esbuild';
import { glob } from 'glob';
import ts from 'typescript';

const components = glob.sync("packages/**/src/index.ts");
const indexPath = "packages/index.ts";
const components = glob.sync('packages/**/src/index.ts');
const indexPath = 'packages/index.ts';

const esbuildDefaults = {
bundle: true,
format: "esm",
format: 'esm',
sourcemap: true,
target: "es2017",
target: 'es2017',
minify: false,
external: ["react", "@lingui/core"],
external: ['react', '@lingui/core'],
};

function generateTypeDefinitions(inputFilePath, packageName, outDir) {
let listOfTsFiles = [];
const options = {
module: ts.ModuleKind.NodeNext,
lib: ["DOM", "ES2020"],
lib: ['DOM', 'ES2020'],
target: ts.ScriptTarget.ES2020,
sourceMap: true,
strict: true,
Expand All @@ -36,7 +37,7 @@ function generateTypeDefinitions(inputFilePath, packageName, outDir) {
allowSyntheticDefaultImports: true,
strictNullChecks: true,
outDir: outDir,
}
};
const host = ts.createCompilerHost(options);
host.writeFile = (fileName, contents) => listOfTsFiles.push({ fileName, contents });

Expand All @@ -51,7 +52,7 @@ function generateTypeDefinitions(inputFilePath, packageName, outDir) {
// Doing this hack since typescript sometimes doesn't output the correct path
let packageTypePath = file.fileName.replace(outDir, '').replace('src/', '').replace(`${packageName}/`, '');
const updatedFilename = outDir + packageTypePath;

fs.mkdirSync(updatedFilename.split('/').slice(0, -1).join('/'), { recursive: true });
fs.writeFileSync(updatedFilename, file.contents);
});
Expand All @@ -62,7 +63,7 @@ function buildComponents(outDir, extraBuildOptions = {}) {
const regex = /\/(\w+)\//;
const match = item.match(regex);

if (item.includes("utils")) return;
if (item.includes('utils')) return;
console.log(`react: building ${match[1]}.js`);

try {
Expand All @@ -72,15 +73,15 @@ function buildComponents(outDir, extraBuildOptions = {}) {
...esbuildDefaults,
...extraBuildOptions,
});
generateTypeDefinitions(item, match[1],`${outDir}/packages/${match[1]}/`);
generateTypeDefinitions(item, match[1], `${outDir}/packages/${match[1]}/`);
} catch (err) {
console.error(err);
}
});
}

async function buildIndex(outDir, extraBuildOptions = {}) {
console.log("react: building index.js");
console.log('react: building index.js');
try {
// ESM build
await esbuild.build({
Expand All @@ -94,15 +95,15 @@ async function buildIndex(outDir, extraBuildOptions = {}) {
...esbuildDefaults,
entryPoints: [indexPath],
outfile: `${outDir}/index.cjs`,
format: "cjs",
format: 'cjs',
...extraBuildOptions,
});
} catch (err) {
console.error(err);
}
}

console.log("Building react");
console.log('Building react');

buildComponents("dist/npm");
buildIndex("dist/npm");
buildComponents('dist/npm');
buildIndex('dist/npm');
8 changes: 2 additions & 6 deletions esbuild.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ok } from 'node:assert';

import * as eik from '@eik/esbuild-plugin';
import esbuild from 'esbuild';

Expand All @@ -11,12 +12,7 @@ const versions = new Map([

const version = process.argv[2];
const reactVersions = Array.from(versions.keys());
ok(
reactVersions.includes(version),
`Version argument is required. Must be one of: ${reactVersions.join(
',',
)}. Eg. 'node esbuild.mjs 18'`,
);
ok(reactVersions.includes(version), `Version argument is required. Must be one of: ${reactVersions.join(',')}. Eg. 'node esbuild.mjs 18'`);

await eik.load({
urls: [`https://assets.finn.no/map/react/${versions.get(version)}`],
Expand Down
1 change: 1 addition & 0 deletions lingui.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { LinguiConfig } from '@lingui/conf';

import { supportedLocales } from './packages/i18n';

const config: LinguiConfig = {
Expand Down
8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,8 @@
"build": "pnpm run build:clean && pnpm run build:npm && pnpm run build:eik && pnpm run build:types",
"commit": "cz",
"dev": "storybook dev -p 9003 --ci",
"format": "prettier --write . --ignore-path .gitignore",
"lint:eslint": "eslint . --ext ts,tsx,js,jsx,cjs --max-warnings 0 --ignore-path .gitignore",
"lint:format": "prettier --check . --ignore-path .gitignore",
"lint": "pnpm run lint:format && pnpm run lint:eslint",
"lint:check": "eslint . --ext ts,tsx,js,jsx,cjs,mjs --ignore-path .gitignore",
"lint": "eslint . --fix --ext ts,tsx,js,jsx,cjs,mjs --ignore-path .gitignore",
"messages:compile": "lingui compile",
"messages:extract": "lingui extract",
"semantic-release": "semantic-release",
Expand Down Expand Up @@ -112,9 +110,9 @@
"element-collapse": "^1.0.1",
"esbuild": "0.19.11",
"eslint": "^8.56.0",
"@warp-ds/eslint-config": "1.0.5",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
Expand Down
21 changes: 11 additions & 10 deletions packages/_helpers/affix.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from "react";
import { suffix, prefix } from "@warp-ds/css/component-classes";
import { classNames } from "@chbphone55/classnames";
import IconClose16 from "@warp-ds/icons/react/close-16";
import IconSearch16 from "@warp-ds/icons/react/search-16";
import React from 'react';

import { classNames } from '@chbphone55/classnames';
import { prefix, suffix } from '@warp-ds/css/component-classes';
import IconClose16 from '@warp-ds/icons/react/close-16';
import IconSearch16 from '@warp-ds/icons/react/search-16';

interface AffixProps {
/** Defines a string value that labels the affix element. */
"aria-label"?: string;
'aria-label'?: string;

/** Affix added at the beginning of input */
prefix?: boolean;
Expand All @@ -31,10 +32,10 @@ export function Affix(props: AffixProps) {
const classBase = props.prefix ? prefix : suffix;

return React.createElement(
props.label ? "div" : "button",
props.label ? 'div' : 'button',
{
"aria-label": !props.label ? props["aria-label"] : undefined,
type: props.search ? "submit" : props.clear ? "reset" : undefined,
'aria-label': !props.label ? props['aria-label'] : undefined,
type: props.search ? 'submit' : props.clear ? 'reset' : undefined,
onClick: props.onClick,
className: classNames({
[classBase.wrapper]: true,
Expand All @@ -48,6 +49,6 @@ export function Affix(props: AffixProps) {
{props.search && <IconSearch16 />}

{props.label && <span className={classBase.label}>{props.label}</span>}
</>
</>,
);
}
89 changes: 44 additions & 45 deletions packages/_helpers/attention.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { AttentionState, Directions, opposites } from '@warp-ds/core/attention'
import { AttentionVariants, AttentionProps, ReferenceElement } from '../attention/src/props.js'
import { i18n } from '@lingui/core'
import { MutableRefObject, useEffect } from 'react'
import { MutableRefObject, useCallback, useEffect } from 'react';

export const getVariant = (variantProps: AttentionVariants, variantClasses: any) => {
return Object.keys(variantClasses).find((b) => !!variantProps[b]) || ''
}
import { i18n } from '@lingui/core';
import { autoUpdatePosition, opposites } from '@warp-ds/core/attention';
import type { AttentionState, Directions } from '@warp-ds/core/attention';

import type { AttentionProps, AttentionVariants, ReferenceElement } from '../attention/src/props.js';

export const getVariant = (variantProps: AttentionVariants, variantClasses: any) =>
Object.keys(variantClasses).find((b) => !!variantProps[b]) || '';
export const pointingAtDirection = (actualDirection: Directions) => {
switch (opposites[actualDirection]) {
case 'top-start':
Expand All @@ -14,87 +16,84 @@ export const pointingAtDirection = (actualDirection: Directions) => {
return i18n._({
id: 'attention.aria.pointingUp',
message: 'pointing up',
comment:
'Default screenreader message for top direction in the attention component',
})
comment: 'Default screenreader message for top direction in the attention component',
});
case 'right-start':
case 'right':
case 'right-end':
return i18n._({
id: 'attention.aria.pointingRight',
message: 'pointing right',
comment:
'Default screenreader message for right direction in the attention component',
})
comment: 'Default screenreader message for right direction in the attention component',
});
case 'bottom-start':
case 'bottom':
case 'bottom-end':
return i18n._({
id: 'attention.aria.pointingDown',
message: 'pointing down',
comment:
'Default screenreader message for bottom direction in the attention component',
})
comment: 'Default screenreader message for bottom direction in the attention component',
});
case 'left-start':
case 'left':
case 'left-end':
return i18n._({
id: 'attention.aria.pointingLeft',
message: 'pointing left',
comment:
'Default screenreader message for left direction in the attention component',
})
comment: 'Default screenreader message for left direction in the attention component',
});
default:
return ''
return '';
}
}
};

export const activeAttentionType = (props: AttentionProps) => {
switch (true) {
case props.tooltip:
return i18n._({
id: 'attention.aria.tooltip',
message: 'tooltip',
comment:
'Default screenreader message for tooltip in the attention component',
})
comment: 'Default screenreader message for tooltip in the attention component',
});
case props.callout:
return i18n._({
id: 'attention.aria.callout',
message: 'callout speech bubble',
comment:
'Default screenreader message for callout speech bubble in the attention component',
})
comment: 'Default screenreader message for callout speech bubble in the attention component',
});
case props.popover:
return i18n._({
id: 'attention.aria.popover',
message: 'popover speech bubble',
comment:
'Default screenreader message for popover speech bubble in the attention component',
})
comment: 'Default screenreader message for popover speech bubble in the attention component',
});
case props.highlight:
return i18n._({
id: 'attention.aria.highlight',
message: 'highlighted speech bubble',
comment:
'Default screenreader message for highlighted speech bubble in the attention component',
})
comment: 'Default screenreader message for highlighted speech bubble in the attention component',
});
default:
return ''
return '';
}
}
};

export const useAutoUpdatePosition = (
targetEl: MutableRefObject<ReferenceElement | null> | undefined,
isShowing: boolean | undefined,
targetEl: MutableRefObject<ReferenceElement | null> | undefined,
isShowing: boolean | undefined,
attentionEl: MutableRefObject<HTMLDivElement | null>,
autoUpdatePosition: (state: AttentionState) => void,
attentionState: AttentionState) => {
attentionState: AttentionState,
) => {
const memoizedAutoUpdatePosition = useCallback(() => autoUpdatePosition(attentionState), [attentionState]);

useEffect(() => {
if (isShowing && targetEl && attentionEl) {
// starts the autoUpdate, making sure the attention elements's position stays anchored to the target element
const cleanup = autoUpdatePosition(attentionState)
return cleanup
if (isShowing && targetEl?.current && attentionEl?.current) {
const cleanup = memoizedAutoUpdatePosition();
return cleanup;
}
}, [targetEl, isShowing, attentionEl])
}
// We should return a cleanup function to maintain consistent return type and handle potential cleanups explicitly.
// This ensures compatibility with TypeScript's type expectations and React's cleanup mechanism.
// Therefore we return an empty function here:
return () => {};
}, [targetEl, isShowing, attentionEl, memoizedAutoUpdatePosition]);
};
Loading

0 comments on commit d83f799

Please sign in to comment.