mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-10 01:43:43 +00:00
refactor: upgrade react and add compiler
This commit is contained in:
@@ -18,11 +18,12 @@
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"autosize": "^6.0.1",
|
||||
"axios": "^1.9.0",
|
||||
"babel-plugin-react-compiler": "19.1.0-rc.2",
|
||||
"csv-stringify": "^6.4.5",
|
||||
"prismjs": "^1.29.0",
|
||||
"react": "^18.3.1",
|
||||
"react": "^19.1.0",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-fast-compare": "^3.2.2",
|
||||
"react-hook-form": "^7.53.1",
|
||||
"react-icons": "5.4.0",
|
||||
@@ -63,8 +64,8 @@
|
||||
"@sentry/vite-plugin": "^2.16.1",
|
||||
"@tanstack/eslint-plugin-query": "^5.8.4",
|
||||
"@types/prismjs": "^1.26.5",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"@typescript-eslint/eslint-plugin": "catalog:",
|
||||
"@typescript-eslint/parser": "catalog:",
|
||||
"@vitejs/plugin-react": "4.5.1",
|
||||
@@ -74,7 +75,7 @@
|
||||
"eslint-plugin-prettier": "catalog:",
|
||||
"eslint-plugin-react": "^7.32.0",
|
||||
"eslint-plugin-react-compiler": "19.1.0-rc.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"eslint-plugin-simple-import-sort": "^8.0.0",
|
||||
"ontime-types": "workspace:*",
|
||||
"ontime-utils": "workspace:*",
|
||||
@@ -82,7 +83,7 @@
|
||||
"sass": "^1.57.1",
|
||||
"typescript": "catalog:",
|
||||
"vite": "6.3.1",
|
||||
"vite-plugin-compression2": "1.4.0",
|
||||
"vite-plugin-compression2": "2.2.0",
|
||||
"vite-plugin-svgr": "4.3.0",
|
||||
"vite-tsconfig-paths": "5.1.4",
|
||||
"vitest": "catalog:"
|
||||
|
||||
@@ -5,7 +5,7 @@ import autosize from 'autosize/dist/autosize';
|
||||
import Textarea, { type TextareaProps } from '../textarea/Textarea';
|
||||
|
||||
interface AutoTextAreaProps extends TextareaProps {
|
||||
inputref: RefObject<HTMLTextAreaElement>;
|
||||
inputref: RefObject<HTMLTextAreaElement | null>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@ interface UseReactiveTextInputReturn {
|
||||
export default function useReactiveTextInput(
|
||||
initialText: string,
|
||||
submitCallback: (newValue: string) => void,
|
||||
ref: RefObject<HTMLInputElement | HTMLTextAreaElement>,
|
||||
ref: RefObject<HTMLInputElement | HTMLTextAreaElement | null>,
|
||||
options?: {
|
||||
submitOnEnter?: boolean;
|
||||
submitOnCtrlEnter?: boolean;
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
import { MouseEvent, SyntheticEvent, TouchEvent, useMemo, useRef } from 'react';
|
||||
|
||||
type LongPressOptions = {
|
||||
threshold?: number;
|
||||
onStart?: (e: SyntheticEvent) => void;
|
||||
onFinish?: (e: SyntheticEvent) => void;
|
||||
onCancel?: (e: SyntheticEvent) => void;
|
||||
};
|
||||
|
||||
type LongPressFns = {
|
||||
onMouseDown: (e: MouseEvent) => void;
|
||||
onMouseUp: (e: MouseEvent) => void;
|
||||
onMouseLeave: (e: MouseEvent) => void;
|
||||
onTouchStart: (e: TouchEvent) => void;
|
||||
onTouchEnd: (e: TouchEvent) => void;
|
||||
};
|
||||
|
||||
export default function useLongPress(callback: () => void, options: LongPressOptions = {}): LongPressFns {
|
||||
const { threshold = 400, onStart, onFinish, onCancel } = options;
|
||||
const isLongPressActive = useRef(false);
|
||||
const isPressed = useRef(false);
|
||||
const timerId = useRef<NodeJS.Timeout>();
|
||||
|
||||
return useMemo(() => {
|
||||
const start = (event: SyntheticEvent) => {
|
||||
if (onStart) {
|
||||
onStart(event);
|
||||
}
|
||||
|
||||
isPressed.current = true;
|
||||
timerId.current = setTimeout(() => {
|
||||
callback();
|
||||
isLongPressActive.current = true;
|
||||
}, threshold);
|
||||
};
|
||||
|
||||
const cancel = (event: SyntheticEvent) => {
|
||||
if (isLongPressActive.current) {
|
||||
if (onFinish) {
|
||||
onFinish(event);
|
||||
}
|
||||
} else if (isPressed.current) {
|
||||
if (onCancel) {
|
||||
onCancel(event);
|
||||
}
|
||||
}
|
||||
|
||||
isLongPressActive.current = false;
|
||||
isPressed.current = false;
|
||||
|
||||
if (timerId.current) {
|
||||
clearTimeout(timerId.current);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
onMouseDown: start,
|
||||
onMouseUp: cancel,
|
||||
onMouseLeave: cancel,
|
||||
onTouchStart: start,
|
||||
onTouchEnd: cancel,
|
||||
};
|
||||
}, [callback, threshold, onCancel, onFinish, onStart]);
|
||||
}
|
||||
@@ -27,7 +27,7 @@ export default function useMemoisedFn<T extends noop>(fn: T) {
|
||||
// https://github.com/alibaba/hooks/issues/728
|
||||
fnRef.current = useMemo(() => fn, [fn]);
|
||||
|
||||
const memoizedFn = useRef<PickFunction<T>>();
|
||||
const memoizedFn = useRef<PickFunction<T>>(undefined);
|
||||
if (!memoizedFn.current) {
|
||||
memoizedFn.current = function (this, ...args) {
|
||||
return fnRef.current.apply(this, args);
|
||||
|
||||
@@ -22,7 +22,7 @@ type AllowedTags = 'div' | 'form';
|
||||
type SectionProps<C extends AllowedTags> = {
|
||||
as?: C;
|
||||
children: ReactNode;
|
||||
} & JSX.IntrinsicElements[C];
|
||||
} & React.JSX.IntrinsicElements[C];
|
||||
|
||||
export function Section<C extends AllowedTags = 'div'>({ as, className, children, ...props }: SectionProps<C>) {
|
||||
const Element = as ?? 'div';
|
||||
@@ -46,7 +46,7 @@ export function Paragraph({ children }: { children: ReactNode }) {
|
||||
return <p className={style.paragraph}>{children}</p>;
|
||||
}
|
||||
|
||||
export function Card({ children, className, ...props }: { children: ReactNode } & JSX.IntrinsicElements['div']) {
|
||||
export function Card({ children, className, ...props }: { children: ReactNode } & React.JSX.IntrinsicElements['div']) {
|
||||
return (
|
||||
<div className={cx([style.card, className])} {...props}>
|
||||
{children}
|
||||
@@ -107,7 +107,7 @@ export function BlockQuote({ children }: { children: ReactNode }) {
|
||||
return <blockquote className={style.blockquote}>{children}</blockquote>;
|
||||
}
|
||||
|
||||
export function Error({ children, className }: { children: ReactNode } & JSX.IntrinsicElements['div']) {
|
||||
export function Error({ children, className }: { children: ReactNode } & React.JSX.IntrinsicElements['div']) {
|
||||
return <div className={cx([style.fieldError, className])}>{children}</div>;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { memo, RefObject, SyntheticEvent } from 'react';
|
||||
import { useLongPress } from '@mantine/hooks';
|
||||
import { MILLIS_PER_MINUTE, MILLIS_PER_SECOND } from 'ontime-utils';
|
||||
|
||||
import DelayIndicator from '../../../common/components/delay-indicator/DelayIndicator';
|
||||
import useLongPress from '../../../common/hooks/useLongPress';
|
||||
import { cx, getAccessibleColour } from '../../../common/utils/styleUtils';
|
||||
import { formatDuration, useTimeUntilStart } from '../../../common/utils/time';
|
||||
import RunningTime from '../../viewers/common/running-time/RunningTime';
|
||||
@@ -23,7 +23,7 @@ interface OperatorEventProps {
|
||||
isLinkedToLoaded: boolean;
|
||||
isSelected: boolean;
|
||||
isPast: boolean;
|
||||
selectedRef?: RefObject<HTMLDivElement>;
|
||||
selectedRef?: RefObject<HTMLDivElement | null>;
|
||||
subscribed: Subscribed;
|
||||
totalGap: number;
|
||||
onLongPress: (event: EditEvent) => void;
|
||||
@@ -48,6 +48,9 @@ function OperatorEvent({
|
||||
totalGap,
|
||||
onLongPress,
|
||||
}: OperatorEventProps) {
|
||||
/**
|
||||
* gather behaviour for long press and context menu
|
||||
*/
|
||||
const handleLongPress = (event?: SyntheticEvent) => {
|
||||
// we dont have an event out of useLongPress
|
||||
event?.preventDefault();
|
||||
@@ -56,7 +59,7 @@ function OperatorEvent({
|
||||
}
|
||||
};
|
||||
|
||||
const mouseHandlers = useLongPress(handleLongPress, { threshold: 800 });
|
||||
const mouseHandlers = useLongPress(handleLongPress);
|
||||
const cueColours = colour && getAccessibleColour(colour);
|
||||
|
||||
const operatorClasses = cx([
|
||||
|
||||
@@ -19,7 +19,7 @@ interface ScheduleContextState {
|
||||
selectedEventId: string | null;
|
||||
numPages: number;
|
||||
visiblePage: number;
|
||||
containerRef: RefObject<HTMLUListElement>;
|
||||
containerRef: RefObject<HTMLUListElement | null>;
|
||||
}
|
||||
|
||||
const ScheduleContext = createContext<ScheduleContextState | undefined>(undefined);
|
||||
@@ -39,7 +39,7 @@ export const ScheduleProvider = ({ children, selectedEventId }: PropsWithChildre
|
||||
const [visiblePage, setVisiblePage] = useState(0);
|
||||
|
||||
const lastIndex = useRef(-1);
|
||||
const paginator = useRef<NodeJS.Timeout>();
|
||||
const paginator = useRef<NodeJS.Timeout>(undefined);
|
||||
|
||||
const containerRef = useRef<HTMLUListElement>(null);
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import { cleanup } from './rowObserver';
|
||||
|
||||
interface CuesheetBodyProps {
|
||||
rowModel: RowModel<OntimeEntry>;
|
||||
selectedRef: RefObject<HTMLTableRowElement>;
|
||||
selectedRef: RefObject<HTMLTableRowElement | null>;
|
||||
table: Table<OntimeEntry>;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,18 @@ import { ONTIME_VERSION } from './src/ONTIME_VERSION';
|
||||
|
||||
const sentryAuthToken = process.env.SENTRY_AUTH_TOKEN;
|
||||
const isDev = process.env.NODE_ENV === 'local' || process.env.NODE_ENV === 'development';
|
||||
const ReactCompilerConfig = {
|
||||
runtimeModule: '@/mycache',
|
||||
};
|
||||
|
||||
export default defineConfig({
|
||||
base: './', // Ontime cloud: we use relative paths to allow them to reference a dynamic base set at runtime
|
||||
plugins: [
|
||||
react(),
|
||||
react({
|
||||
babel: {
|
||||
plugins: [['babel-plugin-react-compiler', ReactCompilerConfig]],
|
||||
},
|
||||
}),
|
||||
svgrPlugin(),
|
||||
!isDev &&
|
||||
sentryVitePlugin({
|
||||
|
||||
Reference in New Issue
Block a user