Skip to content

Commit dfdca49

Browse files
committed
core: Added useLazyRef hook
1 parent 9021488 commit dfdca49

14 files changed

Lines changed: 67 additions & 49 deletions

File tree

packages/apps/logic-sim/src/components/CircuitView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useEffect, useRef } from "react";
22
import styles from "./CircuitView.module.css";
3-
import { App, ClickAction, Divider, DropdownAction, HeaderMenu, openUrl, useAppFolder, useManualContextMenu } from "@prozilla-os/core";
3+
import { App, ClickAction, Divider, DropdownAction, HeaderMenu, openUrl, useAppFolder, useLazyRef, useManualContextMenu } from "@prozilla-os/core";
44
import { Circuit } from "../core/circuit";
55
import { ChipsManager } from "../core/chips/chipsManager";
66

@@ -10,7 +10,7 @@ interface CircuitViewProps {
1010

1111
export function CircuitView({ app }: CircuitViewProps) {
1212
const virtualFolder = useAppFolder(app);
13-
const circuitRef = useRef(new Circuit("Chip", "#000", 2, 1));
13+
const circuitRef = useLazyRef(() => new Circuit("Chip", "#000", 2, 1));
1414
const canvasRef = useRef<HTMLCanvasElement | null>(null);
1515
const { openContextMenu } = useManualContextMenu();
1616

packages/apps/terminal/src/components/InputLine.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { Ansi } from "./Ansi";
66
interface InputLineProps {
77
value: string;
88
prefix: string;
9-
onChange: (event: ChangeEvent) => void;
10-
onKeyUp?: (event: KeyboardEvent) => void;
11-
onKeyDown?: (event: KeyboardEvent) => void;
9+
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
10+
onKeyUp?: (event: KeyboardEvent<HTMLInputElement>) => void;
11+
onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
1212
inputRef: MutableRefObject<HTMLInputElement>;
1313
}
1414

packages/apps/terminal/src/components/Terminal.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { MouseEventHandler, MutableRefObject, useEffect, useRef, useState } from "react";
1+
import { ChangeEventHandler, KeyboardEventHandler, MouseEventHandler, MutableRefObject, useEffect, useRef, useState } from "react";
22
import styles from "./Terminal.module.css";
33
import { OutputLine } from "./OutputLine";
44
import { InputLine } from "./InputLine";
@@ -118,7 +118,7 @@ export function Terminal({ app, path: startPath, input, setTitle, close: exit, a
118118
setStream(stream);
119119
setStreamFocused(false);
120120

121-
const onKeyDown = (event: KeyboardEvent) => {
121+
const onKeyDown = (event: globalThis.KeyboardEvent) => {
122122
if (active && (event.ctrlKey || event.metaKey) && event.key === "c") {
123123
stream.stop();
124124
}
@@ -320,7 +320,7 @@ export function Terminal({ app, path: startPath, input, setTitle, close: exit, a
320320
setHistoryIndex(index);
321321
};
322322

323-
const onKeyDown = (event: React.KeyboardEvent) => {
323+
const onKeyDown: KeyboardEventHandler<HTMLInputElement> = (event) => {
324324
const value = (event.target as HTMLInputElement).value;
325325
const { key } = event;
326326

@@ -338,8 +338,8 @@ export function Terminal({ app, path: startPath, input, setTitle, close: exit, a
338338
}
339339
};
340340

341-
const onChange = (event: React.ChangeEvent) => {
342-
const value = (event.target as HTMLInputElement).value;
341+
const onChange: ChangeEventHandler<HTMLInputElement> = (event) => {
342+
const value = event.target.value;
343343
return setInputValue(value);
344344
};
345345

@@ -357,7 +357,7 @@ export function Terminal({ app, path: startPath, input, setTitle, close: exit, a
357357
});
358358
};
359359

360-
const onMouseDown = (event: MouseEvent) => {
360+
const onMouseDown: MouseEventHandler<HTMLDivElement> = (event) => {
361361
focus?.(event);
362362

363363
if (event.button === 2) {
@@ -371,20 +371,20 @@ export function Terminal({ app, path: startPath, input, setTitle, close: exit, a
371371
}
372372
};
373373

374-
const onContextMenu = (event: Event) => {
374+
const onContextMenu: MouseEventHandler<HTMLDivElement> = (event) => {
375375
event.preventDefault();
376376
};
377377

378378
return (
379379
<div
380380
ref={ref}
381381
className={styles.Terminal}
382-
onMouseDown={onMouseDown as unknown as MouseEventHandler}
383-
onContextMenu={onContextMenu as unknown as MouseEventHandler}
382+
onMouseDown={onMouseDown}
383+
onContextMenu={onContextMenu}
384384
onClick={(event) => {
385385
if (window.getSelection()?.toString() === "") {
386386
event.preventDefault();
387-
(inputRef.current)?.focus();
387+
inputRef.current?.focus();
388388
}
389389
}}
390390
>

packages/core/src/components/windows/WindowView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ export interface WindowProps extends WindowOptions {
3636
/** Function that sets the icon URL of the window. */
3737
setIconUrl?: React.Dispatch<React.SetStateAction<string>>;
3838
/** Function that closes the window. */
39-
close?: (event?: Event) => void;
39+
close?: (event?: Event | React.UIEvent) => void;
4040
/** Function that brings the window in focus. */
41-
focus?: (event?: Event, force?: boolean) => void;
41+
focus?: (event?: Event | React.UIEvent, force?: boolean) => void;
4242
/** Whether the window is currently focused and should allow interactions. */
4343
active?: boolean;
4444
/** Whether to start the window in minimized mode. */

packages/core/src/hooks/_utils/classNames.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ const MODIFIER_PREFIX = "--";
77

88
/**
99
* Generates static class name using BEM notation.
10+
* @param block - The name of the block.
11+
* @param element - The name of the element.
12+
* @param modifier - The name of the modifier(s).
1013
*/
1114
export function useStaticClassName(block?: string, element?: string, modifier?: string | string[]) {
1215
return useMemo(() => {
@@ -40,7 +43,11 @@ export function useStaticClassName(block?: string, element?: string, modifier?:
4043
}
4144

4245
/**
43-
* Combine class names and an optional static class name.
46+
* Combines class names and an optional static class name.
47+
* @param classNames - The class names to combine.
48+
* @param block - The name of the block.
49+
* @param element - The name of the element.
50+
* @param modifier - The name of the modifier(s).
4451
*/
4552
export function useClassNames(classNames: (string | undefined)[], block?: string, element?: string, modifier?: string | string[]) {
4653
const staticClassName = useStaticClassName(block, element, modifier);

packages/core/src/hooks/_utils/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export * from "./mouse";
44
export * from "./outsideClick";
55
export * from "./screen";
66
export * from "./scrollWithShadows";
7-
export * from "./classNames";
7+
export * from "./classNames";
8+
export * from "./lazyRef";
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { MutableRefObject, useRef } from "react";
2+
3+
export function useLazyRef<T>(create: () => T) {
4+
const ref = useRef<T | null>(null);
5+
if (ref.current === null) {
6+
ref.current = create();
7+
}
8+
return ref as MutableRefObject<T>;
9+
}

packages/core/src/hooks/modals/modalsManagerProvider.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ import { FC, ReactNode } from "react";
22
import { ModalsProvider } from "./modalsProvider";
33
import { modalsManagerContext } from "./modalsManagerContext";
44
import { ModalsManager } from "../../features";
5+
import { useLazyRef } from "../_utils";
56

67
export const ModalsManagerProvider: FC<{ children: ReactNode }> = ({ children }) => {
7-
const modalsManager = new ModalsManager();
8+
const modalsManagerRef = useLazyRef(() => new ModalsManager());
89

9-
return (
10-
<modalsManagerContext.Provider value={modalsManager}>
11-
<ModalsProvider modalsManager={modalsManager}>
12-
{children}
13-
</ModalsProvider>
14-
</modalsManagerContext.Provider>
15-
);
10+
return <modalsManagerContext.Provider value={modalsManagerRef.current}>
11+
<ModalsProvider modalsManager={modalsManagerRef.current}>
12+
{children}
13+
</ModalsProvider>
14+
</modalsManagerContext.Provider>;
1615
};

packages/core/src/hooks/settings/settingsManagerProvider.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ import { FC, ReactNode } from "react";
22
import { useVirtualRoot } from "../virtual-drive/virtualRootContext";
33
import { SettingsManagerContext } from "./settingsManagerContext";
44
import { SettingsManager } from "../../features";
5+
import { useLazyRef } from "../_utils";
56

67
export const SettingsManagerProvider: FC<{ children: ReactNode }> = ({ children }) => {
78
const virtualRoot = useVirtualRoot();
89
if (virtualRoot == null) throw new Error("SettingsManager is missing VirtualRoot");
9-
const settingsManager = new SettingsManager(virtualRoot);
10+
const settingsManagerRef = useLazyRef(() => new SettingsManager(virtualRoot));
1011

11-
return (
12-
<SettingsManagerContext.Provider value={settingsManager}>
13-
{children}
14-
</SettingsManagerContext.Provider>
15-
);
12+
return <SettingsManagerContext.Provider value={settingsManagerRef.current}>
13+
{children}
14+
</SettingsManagerContext.Provider>;
1615
};

packages/core/src/hooks/system/systemManagerProvider.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { FC, ReactNode } from "react";
22
import { SystemManagerContext } from "./systemManagerContext";
33
import { SystemManager, SystemManagerParams } from "../../features/system/systemManager";
4+
import { useLazyRef } from "../_utils";
45

56
export interface SystemManagerProviderProps {
67
systemName: SystemManagerParams["systemName"];
@@ -18,9 +19,9 @@ export interface SystemManagerProviderProps {
1819

1920
export const SystemManagerProvider: FC<SystemManagerProviderProps> = (props) => {
2021
const { children, ...systemManagerParams } = props;
21-
const systemManager = new SystemManager(systemManagerParams);
22+
const systemManagerRef = useLazyRef(() => new SystemManager(systemManagerParams));
2223

23-
return <SystemManagerContext.Provider value={systemManager}>
24+
return <SystemManagerContext.Provider value={systemManagerRef.current}>
2425
{children}
2526
</SystemManagerContext.Provider>;
2627
};

0 commit comments

Comments
 (0)