Skip to content

Commit d89bda0

Browse files
Hmvefavna
andauthored
fix: update project to React19, Tailwind 4x and DasisyUI 5.x (#426)
* refactor: update all packages of the main project incl. update to react 19 - fixed most of the linter issues - fixed typescript issues - added tsconfig.typedoc.json to handle typedoc issues - demo project will follow * refactor: update demo project dependencies to 4.2.0 - Bump version to 4.2.0 - Update demo to Tailwind CSS 4.x - Update demo to DaisyUI 5.x - Replace autoprefixer with @parcel/transformer-postcss - Resolve all linter issues - Move theme definition to index.css (tailwind.config.js deprecated) - **Note**: Current bug in PostCSS with new Tailwind version - Apply patch from this PR to run the demo: postcss/postcss#2046 - New PostCSS version expected later this week * fix: some files got lost - sorry * Update package.json ok didn't know that. Co-authored-by: Jeroen Claassens <jeroen.claassens@live.nl> --------- Co-authored-by: Jeroen Claassens <jeroen.claassens@live.nl>
1 parent b8de408 commit d89bda0

17 files changed

+2872
-3327
lines changed

.eslintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
}
1616
},
1717
"rules": {
18+
"@typescript-eslint/no-throw-literal": "off",
1819
"no-extra-label": "warn",
1920
"no-iterator": "warn",
2021
"no-label-var": "warn",

demo/.postcssrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"plugins": {
3-
"tailwindcss": {}
3+
"@tailwindcss/postcss": {}
44
}
5-
}
5+
}

demo/components/IfWithPromise.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ const IfWithPromise: React.FC<Props> = ({ resolutionReturnValue, rejectionReturn
2424
const createPromise = (shouldResolve: boolean) => {
2525
const newPromise: ExtendedPromise = new Promise((resolve, reject) => {
2626
setTimeout(() => {
27-
shouldResolve ? resolve(resolutionReturnValue) : reject(rejectionReturnValue);
27+
if (shouldResolve) {
28+
resolve(resolutionReturnValue);
29+
} else {
30+
reject(rejectionReturnValue);
31+
}
2832
}, delay * 1000);
2933
});
3034
newPromise._id = currentPromiseId.current;

demo/index.css

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
1-
@tailwind base;
2-
@tailwind components;
3-
@tailwind utilities;
1+
@import 'tailwindcss';
2+
@plugin "daisyui";
43

5-
body,
6-
html {
7-
margin: 0;
8-
padding: 0;
4+
@plugin "daisyui/theme" {
5+
name: 'dark';
6+
default: true;
7+
--color-primary: '#5865f2';
8+
--color-secondary: '#ed4245';
9+
--color-primary-content: '#000000';
10+
--color-accent: '#57f287';
11+
--color-accent-content: : '#000000';
12+
--color-neutral: '#1f2123';
13+
--color-neutral-content: '#ffffff';
14+
--color-base-100: '#2c2f33';
15+
--color-base-200: '#212123';
16+
--color-base-300: '#0e0f10';
17+
--color-base-content: '#ffffff';
18+
--color-info: '#2094f3';
19+
--color-success: '#009485';
20+
--color-warning: '#ff9900';
21+
--color-error: '#ff5724';
922
}
1023

1124
* {
@@ -14,6 +27,8 @@ html {
1427

1528
html,
1629
body {
30+
margin: 0;
31+
padding: 0;
1732
display: grid;
1833
place-content: center;
1934
height: 100vh;

demo/index.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import './index.css';
2+
13
import * as React from 'react';
2-
import * as ReactDOM from 'react-dom';
4+
import { createRoot } from 'react-dom/client';
5+
36
import IfThen from './components/IfThen';
47
import IfThenElse from './components/IfThenElse';
58
import IfWithPromise from './components/IfWithPromise';
6-
import './index.css';
79

810
const App = () => {
911
return (
@@ -38,4 +40,10 @@ const App = () => {
3840
);
3941
};
4042

41-
ReactDOM.render(<App />, document.getElementById('root'));
43+
const rootElement = document.getElementById('root');
44+
if (rootElement) {
45+
const root = createRoot(rootElement);
46+
root.render(<App />);
47+
} else {
48+
console.error('Element with id "root" not found.');
49+
}

demo/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
"build": "parcel build index.html"
1111
},
1212
"devDependencies": {
13-
"autoprefixer": "^10.4.21",
14-
"daisyui": "^4.12.24",
13+
"@parcel/transformer-postcss": "^2.15.2",
14+
"@tailwindcss/postcss": "^4.1.7",
15+
"daisyui": "^5.0.37",
1516
"parcel": "^2.15.2",
1617
"postcss": "^8.5.3",
17-
"tailwindcss": "^3.4.17",
18-
"typescript": "^5.5.2"
18+
"tailwindcss": "^4.1.7",
19+
"typescript": "^5.8.3"
1920
}
2021
}

demo/tailwind.config.js

Lines changed: 0 additions & 40 deletions
This file was deleted.

package.json

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,34 +47,37 @@
4747
"@testing-library/dom": "^10.4.0",
4848
"@testing-library/jest-dom": "^6.6.3",
4949
"@testing-library/react": "^16.3.0",
50+
"@types/entities": "^2.0.2",
5051
"@types/node": "^22.15.21",
51-
"@types/react": "^18.3.22",
52-
"@types/react-dom": "^18.3.7",
53-
"@typescript-eslint/eslint-plugin": "^7.13.1",
54-
"@typescript-eslint/parser": "^7.13.1",
52+
"@types/react": "^19.1.5",
53+
"@types/react-dom": "^19.1.5",
54+
"@typescript-eslint/eslint-plugin": "^8.32.1",
55+
"@typescript-eslint/parser": "^8.32.1",
56+
"ansi-regex": "^6.1.0",
5557
"cz-conventional-changelog": "^3.3.0",
5658
"dts-cli": "^2.0.5",
57-
"eslint": "^8.57.1",
59+
"eslint": "^9.27.0",
5860
"eslint-config-prettier": "^10.1.5",
59-
"eslint-config-react-app": "^7.0.1",
6061
"eslint-plugin-import": "^2.31.0",
6162
"eslint-plugin-jsx-a11y": "^6.10.2",
6263
"eslint-plugin-prettier": "^5.4.0",
6364
"eslint-plugin-react": "^7.37.5",
6465
"eslint-plugin-react-hooks": "^5.2.0",
66+
"jest": "^29.7.0",
6567
"lint-staged": "^16.0.0",
6668
"prettier": "^3.5.3",
67-
"react": "^18.3.1",
68-
"react-dom": "^18.3.1",
69+
"react": "^19.1.0",
70+
"react-dom": "^19.1.0",
6971
"ts-jest": "^29.3.4",
70-
"typedoc": "^0.26.1",
71-
"typescript": "^5.5.2"
72+
"typedoc": "^0.28.4",
73+
"typedoc-plugin-markdown": "^4.6.3",
74+
"typescript": "^5.8.3"
7275
},
7376
"engines": {
7477
"node": ">=12"
7578
},
7679
"peerDependencies": {
77-
"react": "^16.x || ^17.x || ^18.x"
80+
"react": "^16.x || ^17.x || ^18.x || ^19.x"
7881
},
7982
"commitlint": {
8083
"extends": [
@@ -92,9 +95,9 @@
9295
},
9396
"resolutions": {
9497
"prettier": "^3.5.3",
95-
"@types/react-dom": "^18.3.7",
96-
"@types/react": "^18.3.22",
97-
"@typescript-eslint/eslint-plugin": "^7.13.1",
98+
"@types/react": "^19.1.5",
99+
"@types/react-dom": "^19.1.5",
100+
"@typescript-eslint/eslint-plugin": "^8.32.1",
98101
"@typescript-eslint/parser": "^7.13.1",
99102
"cz-conventional-changelog": "^3.3.0",
100103
"eslint-config-prettier": "^10.1.5",
@@ -105,10 +108,10 @@
105108
"eslint-plugin-react-hooks": "^5.2.0",
106109
"eslint-plugin-react": "^7.37.5",
107110
"eslint": "^8.57.1",
108-
"react-dom": "^18.3.1",
111+
"react-dom": "^19.1.0",
109112
"ansi-regex": "^5.0.1",
110113
"minimist": "^1.2.8",
111-
"react": "^18.3.1",
114+
"react": "^19.1.0",
112115
"@sapphire/ts-config@^4.0.1": "patch:@sapphire/ts-config@npm%3A4.0.0#./.yarn/patches/@sapphire-ts-config-npm-4.0.0-cfd20d4fc5.patch",
113116
"@types/testing-library__jest-dom@^5.14.8": "patch:@types/testing-library__jest-dom@npm%3A5.14.7#./.yarn/patches/@types-testing-library__jest-dom-npm-5.14.7-9c1df8c5da.patch",
114117
"@types/testing-library__jest-dom@^5.9.1": "patch:@types/testing-library__jest-dom@npm%3A5.14.7#./.yarn/patches/@types-testing-library__jest-dom-npm-5.14.7-9c1df8c5da.patch"

src/IfAsync.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React, { Fragment, useEffect, useMemo, useRef, useState, type PropsWithChildren, type ReactElement } from 'react';
1+
import * as React from 'react';
2+
import { Fragment, useEffect, useMemo, useRef, useState, type PropsWithChildren, type ReactElement } from 'react';
23
import { Else } from './Else';
34
import { Fallback } from './Fallback';
45
import { Then } from './Then';
@@ -69,12 +70,13 @@ export function IfAsync<T = any>({ promise, keepAlive = false, children }: Props
6970

7071
// Inject caught error
7172
let elseElement = hasElse;
72-
if (typeof hasElse.props.children === 'function') {
73+
const hasElseProps = hasElse.props as { children: any };
74+
if (typeof hasElseProps.children === 'function') {
7375
elseElement = {
7476
...hasElse,
7577
props: {
76-
...hasElse.props,
77-
children: () => hasElse.props.children(returnValue, history.current, cancellablePromise.promise)
78+
...hasElseProps,
79+
children: () => hasElseProps.children(returnValue, history.current, cancellablePromise.promise)
7880
}
7981
};
8082
}
@@ -87,13 +89,13 @@ export function IfAsync<T = any>({ promise, keepAlive = false, children }: Props
8789

8890
// Inject promise return value
8991
let thenElement = hasThen;
90-
91-
if (typeof hasThen.props.children === 'function') {
92+
const hasThenProps = hasThen.props as { children: any };
93+
if (typeof hasThenProps.children === 'function') {
9294
thenElement = {
9395
...hasThen,
9496
props: {
95-
...hasThen.props,
96-
children: () => hasThen.props.children(returnValue, history.current, cancellablePromise.promise)
97+
...hasThenProps,
98+
children: () => hasThenProps.children(returnValue, history.current, cancellablePromise.promise)
9799
}
98100
};
99101
}

src/Switch.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React, { type ReactElement } from 'react';
1+
import * as React from 'react';
2+
import { type ReactElement } from 'react';
23
import { Case } from './Case';
34
import { Default } from './Default';
45
import { getConditionResult } from './getConditionResults';
@@ -33,9 +34,8 @@ export const Switch: FCWithImplicitChildren = ({ children }) => {
3334
}
3435

3536
if (!matchingCase && child.type === Case) {
36-
const { condition } = child.props;
37-
38-
const conditionResult = getConditionResult(condition);
37+
const childProps = child.props as any;
38+
const conditionResult = getConditionResult(childProps.condition);
3939

4040
if (conditionResult) {
4141
matchingCase = child;

src/isThenable.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Full license: https://github.com/sapphiredev/utilities/blob/main/LICENSE.md
88
*/
99

10-
/* eslint-disable @typescript-eslint/ban-types */
10+
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
1111

1212
interface Thenable {
1313
then: Function;

src/types.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { FunctionComponent, PropsWithChildren, ReactNode } from 'react';
1+
import type { FunctionComponent, JSX, PropsWithChildren, ReactNode } from 'react';
22

33
/**
44
* Type for a value that can properly be parsed by `Boolean(...)`
@@ -59,7 +59,6 @@ export type FCWithImplicitChildren<P = NonNullObject> = FunctionComponentWithImp
5959

6060
export type FunctionComponentWithImplicitChildren<P = NonNullObject> = FunctionComponent<CustomPropsWithChildren<P>>;
6161

62-
// eslint-disable-next-line @typescript-eslint/ban-types
6362
export type NonNullObject = {} & object;
6463

6564
export type CustomPropsWithChildren<P> = P & { children?: ReactNode | undefined | ((...args: unknown[]) => JSX.Element) };

src/utils.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,13 @@ export const createCancellablePromise = <T>(promise: ExtendablePromise<T>): Canc
3434
const wrappedPromise: ExtendablePromise<T> = new Promise(async (res, rej) => {
3535
try {
3636
const d = await promise;
37-
return !isCancelled.value && res(d);
37+
if (!isCancelled.value) {
38+
res(d);
39+
}
3840
} catch (error) {
39-
!isCancelled.value && rej(error);
41+
if (!isCancelled.value) {
42+
rej(error);
43+
}
4044
}
4145
});
4246

test/If.test.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,7 @@ describe('<If /> component', () => {
216216
render(
217217
<If condition={extendedPromise}>
218218
<Then>
219-
{(data: any, history: any, promise: any) => {
220-
data;
221-
history; // 'skip declared but value never read' error
219+
{(_data: any, _history: any, promise: any) => {
222220
return <span data-testid="thenChild">{promise.testValue}</span>;
223221
}}
224222
</Then>
@@ -397,9 +395,7 @@ describe('<If /> component', () => {
397395
render(
398396
<If condition={extendedPromise}>
399397
<Else>
400-
{(data: any, history: any, promise: any) => {
401-
data;
402-
history; // 'skip declared but value never read' error
398+
{(_data: any, _history: any, promise: any) => {
403399
return <span data-testid="elseChild">{promise.testValue}</span>;
404400
}}
405401
</Else>

tsconfig.typedoc.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "./src/tsconfig.json",
3+
"compilerOptions": {
4+
"moduleResolution": "nodenext",
5+
"module": "NodeNext",
6+
"verbatimModuleSyntax": false
7+
}
8+
}

typedoc.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
"hideGenerator": true,
66
"lightHighlightTheme": "github-light",
77
"darkHighlightTheme": "github-dark",
8-
"markedOptions": {
8+
"markdownItOptions": {
99
"gfm": true,
1010
"mangle": false,
1111
"smartypants": true
1212
},
1313
"name": "react-if",
1414
"out": "./docs/",
1515
"readme": "./README.md",
16-
"tsconfig": "./src/tsconfig.json"
16+
"tsconfig": "./tsconfig.typedoc.json",
17+
"plugin": ["typedoc-plugin-markdown"]
1718
}

0 commit comments

Comments
 (0)