Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testbranch DO MOT MERGE #694

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const {swcLoaderOptions} = require('./config/swc/loaderOptions'); // eslint-disable-line

module.exports = {
testPathIgnorePatterns: ['/node_modules/', '\\.d\\.test\\.ts$'],
moduleDirectories: ['node_modules', '<rootDir>/src'],
modulePathIgnorePatterns: ['<rootDir>/src/app/'],
transformIgnorePatterns: [
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"generate:legacyStory": "plop legacyStory --cwd ./config/plop --dest .",
"lint": "yarn lint:src && yarn lint:config",
"lint:config": "esw \"./config/**/*.{js,jsx,ts,tsx}\"",
"lint:src": "esw \"./src/**/*.{js,jsx,ts,tsx}\"",
"lint:src": "tsc --noEmit --skipLibCheck && esw \"./src/**/*.{js,jsx,ts,tsx}\"",
"lint:watch": "yarn lint:src --watch",
"prepublishOnly": "yarn build",
"prepare": "husky install",
Expand Down Expand Up @@ -237,7 +237,7 @@
"plop": "^2.7.4",
"postcss-flexbugs-fixes": "3.2.0",
"postcss-loader": "^2.1.3",
"prettier": "^2.3.2",
"prettier": "^2.8.8",
"prop-types": "15.6.0",
"react": "16.14.0",
"react-dom": "16.14.0",
Expand Down
34 changes: 21 additions & 13 deletions src/utils/a11y.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
import { AriaAttributes, useEffect } from 'react';

export type AriaLabelRequired =
| {
/**
* Defines a string value that labels the current element.
*/
'aria-label': AriaAttributes['aria-label'];
}
| {
/**
* Identifies the element (or elements) that labels the current element.
*/
'aria-labelledby': AriaAttributes['aria-labelledby'];
};
/**
* Utility type to require one or more from a set of attributes.
*
* For example, this is used to check that `aria-label` or `aria-labelledby` is defined on components when consumed.
* `RequireOneOf<AriaAttributes, ['aria-label', 'aria-labelledby']>` = `{'aria-label': string} | {'aria-labelledby': string}`
*
* More examples can be found in src/utils/a11y.d.test.ts
*
* @typeParam TFrom - Used to get the type of the required attributes
* @typeParam TAttributes - One of these attributes satifies this requirement. Must be given as an array.
*/
export type RequireOneOf<TFrom, TAttributes extends (keyof TFrom)[]> = TAttributes extends [
// Get the first attribute defintion in TAttributes
infer TFirst extends keyof TFrom,
// Get the remaining attribute definitions in TAttributes
...infer TLast extends (keyof TFrom)[]
]
? Required<{ [K in TFirst]: TFrom[K] }> | RequireOneOf<TFrom, TLast>
: never;

export type AriaLabelRequired = RequireOneOf<AriaAttributes, ['aria-label', 'aria-labelledby']>;

/**
* Check if `aria-labelledby` or `aria-label` are defined and are truthy
Expand Down
45 changes: 45 additions & 0 deletions src/utils/a11y.types.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { ReactNode } from 'react';
import { AriaLabelRequired, RequireOneOf } from './a11y';

// https://github.com/type-challenges/type-challenges/blob/main/utils/index.d.ts
// These types are used for testing to check that 2 types are the same
type Expect<T extends true> = T;
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2
? true
: false;

// eslint-disable-next-line @typescript-eslint/no-unused-vars
type cases = [
// If no attributes are defined, type should be never
Expect<Equal<RequireOneOf<{ one: number }, []>, never>>,

// Gets the type of the attribute from the first type parameter
Expect<Equal<RequireOneOf<{ one: number }, ['one']>, { one: number }>>,

// Gets the type and makes the attribute required by removing the ? and removing undefined from the type
Expect<Equal<RequireOneOf<{ one?: number }, ['one']>, { one: number }>>,
Expect<Equal<RequireOneOf<{ one: number | undefined }, ['one']>, { one: number }>>,

// Works with non primitive types and doesn't output any attributes defined in the first parameter
// but not defined in the second
Expect<
Equal<
RequireOneOf<
{ a?: string | number; b: ReactNode; c: string; d?: JSX.Element },
['a', 'b', 'c']
>,
{ a: string | number } | { b: ReactNode } | { c: string }
>
>,

// If a union type is defined in the attributes, the option requires both values in the object
// to satify this type
Expect<
Equal<
RequireOneOf<{ a: number; b: number; c: number }, ['a' | 'b', 'c']>,
{ a: number } | { c: number }
>
>,

Expect<Equal<AriaLabelRequired, { 'aria-label': string } | { 'aria-labelledby': string }>>
];
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3059,7 +3059,7 @@ __metadata:
plop: ^2.7.4
postcss-flexbugs-fixes: 3.2.0
postcss-loader: ^2.1.3
prettier: ^2.3.2
prettier: ^2.8.8
prop-types: 15.6.0
react: 16.14.0
react-aria: ^3.10.0
Expand Down Expand Up @@ -24037,12 +24037,12 @@ __metadata:
languageName: node
linkType: hard

"prettier@npm:^2.3.2":
version: 2.3.2
resolution: "prettier@npm:2.3.2"
"prettier@npm:^2.8.8":
version: 2.8.8
resolution: "prettier@npm:2.8.8"
bin:
prettier: bin-prettier.js
checksum: 17ce5784ac67621c292df58e2da60b2ee150c2d6aebea22a6ad9e52fcd6a5e66c349d0a8436ea3bd8ff9d778920a5f68000d7625b74f43558718a49755aa5259
checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8
languageName: node
linkType: hard

Expand Down
Loading