Files
Bubberstation/tgui/packages/common/react.ts
Jeremiah 0454525d75 Ports React [READY] (#80044)
## About The Pull Request
Moves us from Inferno 7.4.11 to React 18.2. This is a big project! You
might find errors here. Sometimes I get carried away fixing external
issues, I'll try to atomize them into separate PRs.

- [x] Implements React
- [x] CSS kebab to camel case
- [x] Some typescript refactors 
- [x] Atomize what I can
- [x] Fix dropdowns (opens in the wrong location)
- [x] Fix wonky button placement in a few UIs
- [x] Cleanup
## Why It's Good For The Game
- It'd be nice to just have real hooks. Our implementation is probably
the best possible for Inferno, don't get me wrong.
- React is just easier to maintain and easier to read. It's the web dev
standard.

Closes #78221 
## Changelog
🆑
refactor: TGUI V5: The UI has had its entire engine replaced with React
v18.2. This might cause obvious or laughably broken UIs in places you
wouldn't expect. Please report any issues you find to the repo!
/🆑

---------

Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
2023-12-08 22:30:49 +01:00

69 lines
1.5 KiB
TypeScript

/**
* @file
* @copyright 2020 Aleksej Komarov
* @license MIT
*/
/**
* Helper for conditionally adding/removing classes in React
*/
export const classes = (classNames: (string | BooleanLike)[]) => {
let className = '';
for (let i = 0; i < classNames.length; i++) {
const part = classNames[i];
if (typeof part === 'string') {
className += part + ' ';
}
}
return className;
};
/**
* Normalizes children prop, so that it is always an array of VDom
* elements.
*/
export const normalizeChildren = <T>(children: T | T[]) => {
if (Array.isArray(children)) {
return children.flat().filter((value) => value) as T[];
}
if (typeof children === 'object') {
return [children];
}
return [];
};
/**
* Shallowly checks if two objects are different.
* Credit: https://github.com/developit/preact-compat
*/
export const shallowDiffers = (a: object, b: object) => {
let i;
for (i in a) {
if (!(i in b)) {
return true;
}
}
for (i in b) {
if (a[i] !== b[i]) {
return true;
}
}
return false;
};
/**
* A common case in tgui, when you pass a value conditionally, these are
* the types that can fall through the condition.
*/
export type BooleanLike = number | boolean | null | undefined;
/**
* A helper to determine whether the object is renderable by React.
*/
export const canRender = (value: unknown) => {
// prettier-ignore
return value !== undefined
&& value !== null
&& typeof value !== 'boolean';
};