feat: improve column carousel
This commit is contained in:
@@ -454,25 +454,9 @@ async createColumn(column: Column) : Promise<Result<string, string>> {
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async closeColumn(label: string) : Promise<Result<boolean, string>> {
|
||||
async updateColumn(label: string, width: number, height: number, x: number, y: number) : Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("close_column", { label }) };
|
||||
} catch (e) {
|
||||
if(e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async repositionColumn(label: string, x: number, y: number) : Promise<Result<boolean, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("reposition_column", { label, x, y }) };
|
||||
} catch (e) {
|
||||
if(e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async resizeColumn(label: string, width: number, height: number) : Promise<Result<boolean, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("resize_column", { label, width, height }) };
|
||||
return { status: "ok", data: await TAURI_INVOKE("update_column", { label, width, height, x, y }) };
|
||||
} catch (e) {
|
||||
if(e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
@@ -486,6 +470,14 @@ async reloadColumn(label: string) : Promise<Result<boolean, string>> {
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async closeColumn(label: string) : Promise<Result<boolean, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("close_column", { label }) };
|
||||
} catch (e) {
|
||||
if(e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async openWindow(window: Window) : Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("open_window", { window }) };
|
||||
|
||||
@@ -1,107 +1,89 @@
|
||||
import { commands } from "@/commands.gen";
|
||||
import { appColumns } from "@/commons";
|
||||
import { useRect } from "@/system";
|
||||
import type { LumeColumn } from "@/types";
|
||||
import { CaretDown, Check } from "@phosphor-icons/react";
|
||||
import { useParams } from "@tanstack/react-router";
|
||||
import { useStore } from "@tanstack/react-store";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { Menu, MenuItem, PredefinedMenuItem } from "@tauri-apps/api/menu";
|
||||
import { getCurrentWindow } from "@tauri-apps/api/window";
|
||||
import { memo, useCallback, useEffect, useRef, useState } from "react";
|
||||
import { Spinner } from "./spinner";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
|
||||
type WindowEvent = {
|
||||
scroll: boolean;
|
||||
resize: boolean;
|
||||
};
|
||||
|
||||
export const Column = memo(function Column({ column }: { column: LumeColumn }) {
|
||||
export function Column({ column }: { column: LumeColumn }) {
|
||||
const params = useParams({ strict: false });
|
||||
const container = useRef<HTMLDivElement>(null);
|
||||
const webviewLabel = `column-${params.account}_${column.label}`;
|
||||
const webviewLabel = useMemo(
|
||||
() => `column-${params.account}_${column.label}`,
|
||||
[params.account, column.label],
|
||||
);
|
||||
|
||||
const [isCreated, setIsCreated] = useState(false);
|
||||
|
||||
const repositionWebview = useCallback(async () => {
|
||||
if (!container.current) return;
|
||||
|
||||
const newRect = container.current.getBoundingClientRect();
|
||||
await invoke("reposition_column", {
|
||||
label: webviewLabel,
|
||||
x: newRect.x,
|
||||
y: newRect.y,
|
||||
});
|
||||
}, []);
|
||||
|
||||
const resizeWebview = useCallback(async () => {
|
||||
if (!container.current) return;
|
||||
|
||||
const newRect = container.current.getBoundingClientRect();
|
||||
await invoke("resize_column", {
|
||||
label: webviewLabel,
|
||||
width: newRect.width,
|
||||
height: newRect.height,
|
||||
});
|
||||
}, []);
|
||||
const [rect, ref] = useRect();
|
||||
const [error, setError] = useState<string>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isCreated) return;
|
||||
(async () => {
|
||||
if (rect) {
|
||||
const res = await commands.updateColumn(
|
||||
webviewLabel,
|
||||
rect.width,
|
||||
rect.height,
|
||||
rect.x,
|
||||
rect.y,
|
||||
);
|
||||
|
||||
const unlisten = listen<WindowEvent>("child_webview", (data) => {
|
||||
if (data.payload.scroll) repositionWebview();
|
||||
if (data.payload.resize) repositionWebview().then(() => resizeWebview());
|
||||
});
|
||||
|
||||
return () => {
|
||||
unlisten.then((f) => f());
|
||||
};
|
||||
}, [isCreated]);
|
||||
if (res.status === "ok") {
|
||||
console.log("webview is updated: ", webviewLabel);
|
||||
} else {
|
||||
console.log("webview error: ", res.error);
|
||||
}
|
||||
}
|
||||
})();
|
||||
}, [rect]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!container.current) return;
|
||||
const isCreated = window.sessionStorage.getItem(webviewLabel);
|
||||
|
||||
const rect = container.current.getBoundingClientRect();
|
||||
const url = `${column.url}?account=${params.account}&label=${column.label}&name=${column.name}`;
|
||||
if (!isCreated) {
|
||||
const initialRect = ref.current.getBoundingClientRect();
|
||||
|
||||
const prop = {
|
||||
label: webviewLabel,
|
||||
x: rect.x,
|
||||
y: rect.y,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
url,
|
||||
};
|
||||
commands
|
||||
.createColumn({
|
||||
label: webviewLabel,
|
||||
x: initialRect.x,
|
||||
y: initialRect.y,
|
||||
width: initialRect.width,
|
||||
height: initialRect.height,
|
||||
url: `${column.url}?account=${params.account}&label=${column.label}&name=${column.name}`,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
console.log("webview is created: ", webviewLabel);
|
||||
window.sessionStorage.setItem(webviewLabel, "");
|
||||
} else {
|
||||
setError(res.error);
|
||||
}
|
||||
});
|
||||
|
||||
// create new webview
|
||||
invoke("create_column", { column: prop }).then(() => {
|
||||
console.log("created: ", webviewLabel);
|
||||
setIsCreated(true);
|
||||
});
|
||||
|
||||
// close webview when unmounted
|
||||
return () => {
|
||||
invoke("close_column", { label: webviewLabel }).then(() => {
|
||||
console.log("closed: ", webviewLabel);
|
||||
});
|
||||
};
|
||||
return () => {
|
||||
commands.closeColumn(webviewLabel).then((res) => {
|
||||
if (res.status === "ok") {
|
||||
console.log("webview is closed: ", webviewLabel);
|
||||
} else {
|
||||
console.log("webview error: ", res.error);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}, [params.account]);
|
||||
|
||||
return (
|
||||
<div className="h-full w-[440px] shrink-0 border-r border-black/5 dark:border-white/5">
|
||||
<div className="flex flex-col gap-px size-full">
|
||||
<Header label={column.label} />
|
||||
<div ref={container} className="flex-1 size-full">
|
||||
{!isCreated ? (
|
||||
<div className="size-full flex items-center justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div ref={ref} className="flex-1 size-full" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function Header({ label }: { label: string }) {
|
||||
const [title, setTitle] = useState("");
|
||||
|
||||
@@ -32,7 +32,6 @@ import { Route as AccountSettingsRelayImport } from './routes/$account/_settings
|
||||
import { Route as AccountSettingsProfileImport } from './routes/$account/_settings/profile'
|
||||
import { Route as AccountSettingsGeneralImport } from './routes/$account/_settings/general'
|
||||
import { Route as AccountSettingsBitcoinConnectImport } from './routes/$account/_settings/bitcoin-connect'
|
||||
import { Route as AccountAppHomeImport } from './routes/$account/_app/home'
|
||||
import { Route as ColumnsLayoutInterestsIdImport } from './routes/columns/_layout/interests.$id'
|
||||
import { Route as ColumnsLayoutGroupsIdImport } from './routes/columns/_layout/groups.$id'
|
||||
import { Route as ColumnsLayoutCreateNewsfeedUsersImport } from './routes/columns/_layout/create-newsfeed.users'
|
||||
@@ -63,6 +62,7 @@ const ColumnsLayoutNotificationLazyImport = createFileRoute(
|
||||
const ColumnsLayoutLaunchpadLazyImport = createFileRoute(
|
||||
'/columns/_layout/launchpad',
|
||||
)()
|
||||
const AccountAppHomeLazyImport = createFileRoute('/$account/_app/home')()
|
||||
const ColumnsLayoutUsersIdLazyImport = createFileRoute(
|
||||
'/columns/_layout/users/$id',
|
||||
)()
|
||||
@@ -208,6 +208,13 @@ const ColumnsLayoutLaunchpadLazyRoute = ColumnsLayoutLaunchpadLazyImport.update(
|
||||
import('./routes/columns/_layout/launchpad.lazy').then((d) => d.Route),
|
||||
)
|
||||
|
||||
const AccountAppHomeLazyRoute = AccountAppHomeLazyImport.update({
|
||||
path: '/home',
|
||||
getParentRoute: () => AccountAppRoute,
|
||||
} as any).lazy(() =>
|
||||
import('./routes/$account/_app.home.lazy').then((d) => d.Route),
|
||||
)
|
||||
|
||||
const ColumnsLayoutStoriesRoute = ColumnsLayoutStoriesImport.update({
|
||||
path: '/stories',
|
||||
getParentRoute: () => ColumnsLayoutRoute,
|
||||
@@ -271,13 +278,6 @@ const AccountSettingsBitcoinConnectRoute =
|
||||
),
|
||||
)
|
||||
|
||||
const AccountAppHomeRoute = AccountAppHomeImport.update({
|
||||
path: '/home',
|
||||
getParentRoute: () => AccountAppRoute,
|
||||
} as any).lazy(() =>
|
||||
import('./routes/$account/_app/home.lazy').then((d) => d.Route),
|
||||
)
|
||||
|
||||
const ColumnsLayoutUsersIdLazyRoute = ColumnsLayoutUsersIdLazyImport.update({
|
||||
path: '/users/$id',
|
||||
getParentRoute: () => ColumnsLayoutRoute,
|
||||
@@ -457,13 +457,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof EditorIndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/$account/_app/home': {
|
||||
id: '/$account/_app/home'
|
||||
path: '/home'
|
||||
fullPath: '/$account/home'
|
||||
preLoaderRoute: typeof AccountAppHomeImport
|
||||
parentRoute: typeof AccountAppImport
|
||||
}
|
||||
'/$account/_settings/bitcoin-connect': {
|
||||
id: '/$account/_settings/bitcoin-connect'
|
||||
path: '/bitcoin-connect'
|
||||
@@ -527,6 +520,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof ColumnsLayoutStoriesImport
|
||||
parentRoute: typeof ColumnsLayoutImport
|
||||
}
|
||||
'/$account/_app/home': {
|
||||
id: '/$account/_app/home'
|
||||
path: '/home'
|
||||
fullPath: '/$account/home'
|
||||
preLoaderRoute: typeof AccountAppHomeLazyImport
|
||||
parentRoute: typeof AccountAppImport
|
||||
}
|
||||
'/columns/_layout/launchpad': {
|
||||
id: '/columns/_layout/launchpad'
|
||||
path: '/launchpad'
|
||||
@@ -617,11 +617,11 @@ declare module '@tanstack/react-router' {
|
||||
// Create and export the route tree
|
||||
|
||||
interface AccountAppRouteChildren {
|
||||
AccountAppHomeRoute: typeof AccountAppHomeRoute
|
||||
AccountAppHomeLazyRoute: typeof AccountAppHomeLazyRoute
|
||||
}
|
||||
|
||||
const AccountAppRouteChildren: AccountAppRouteChildren = {
|
||||
AccountAppHomeRoute: AccountAppHomeRoute,
|
||||
AccountAppHomeLazyRoute: AccountAppHomeLazyRoute,
|
||||
}
|
||||
|
||||
const AccountAppRouteWithChildren = AccountAppRoute._addFileChildren(
|
||||
@@ -745,7 +745,6 @@ export interface FileRoutesByFullPath {
|
||||
'/auth/import': typeof AuthImportLazyRoute
|
||||
'/auth/new': typeof AuthNewLazyRoute
|
||||
'/editor': typeof EditorIndexRoute
|
||||
'/$account/home': typeof AccountAppHomeRoute
|
||||
'/$account/bitcoin-connect': typeof AccountSettingsBitcoinConnectRoute
|
||||
'/$account/general': typeof AccountSettingsGeneralRoute
|
||||
'/$account/profile': typeof AccountSettingsProfileRoute
|
||||
@@ -755,6 +754,7 @@ export interface FileRoutesByFullPath {
|
||||
'/columns/global': typeof ColumnsLayoutGlobalRoute
|
||||
'/columns/newsfeed': typeof ColumnsLayoutNewsfeedRoute
|
||||
'/columns/stories': typeof ColumnsLayoutStoriesRoute
|
||||
'/$account/home': typeof AccountAppHomeLazyRoute
|
||||
'/columns/launchpad': typeof ColumnsLayoutLaunchpadLazyRoute
|
||||
'/columns/notification': typeof ColumnsLayoutNotificationLazyRoute
|
||||
'/columns/onboarding': typeof ColumnsLayoutOnboardingLazyRoute
|
||||
@@ -785,7 +785,6 @@ export interface FileRoutesByTo {
|
||||
'/auth/import': typeof AuthImportLazyRoute
|
||||
'/auth/new': typeof AuthNewLazyRoute
|
||||
'/editor': typeof EditorIndexRoute
|
||||
'/$account/home': typeof AccountAppHomeRoute
|
||||
'/$account/bitcoin-connect': typeof AccountSettingsBitcoinConnectRoute
|
||||
'/$account/general': typeof AccountSettingsGeneralRoute
|
||||
'/$account/profile': typeof AccountSettingsProfileRoute
|
||||
@@ -795,6 +794,7 @@ export interface FileRoutesByTo {
|
||||
'/columns/global': typeof ColumnsLayoutGlobalRoute
|
||||
'/columns/newsfeed': typeof ColumnsLayoutNewsfeedRoute
|
||||
'/columns/stories': typeof ColumnsLayoutStoriesRoute
|
||||
'/$account/home': typeof AccountAppHomeLazyRoute
|
||||
'/columns/launchpad': typeof ColumnsLayoutLaunchpadLazyRoute
|
||||
'/columns/notification': typeof ColumnsLayoutNotificationLazyRoute
|
||||
'/columns/onboarding': typeof ColumnsLayoutOnboardingLazyRoute
|
||||
@@ -829,7 +829,6 @@ export interface FileRoutesById {
|
||||
'/auth/import': typeof AuthImportLazyRoute
|
||||
'/auth/new': typeof AuthNewLazyRoute
|
||||
'/editor/': typeof EditorIndexRoute
|
||||
'/$account/_app/home': typeof AccountAppHomeRoute
|
||||
'/$account/_settings/bitcoin-connect': typeof AccountSettingsBitcoinConnectRoute
|
||||
'/$account/_settings/general': typeof AccountSettingsGeneralRoute
|
||||
'/$account/_settings/profile': typeof AccountSettingsProfileRoute
|
||||
@@ -839,6 +838,7 @@ export interface FileRoutesById {
|
||||
'/columns/_layout/global': typeof ColumnsLayoutGlobalRoute
|
||||
'/columns/_layout/newsfeed': typeof ColumnsLayoutNewsfeedRoute
|
||||
'/columns/_layout/stories': typeof ColumnsLayoutStoriesRoute
|
||||
'/$account/_app/home': typeof AccountAppHomeLazyRoute
|
||||
'/columns/_layout/launchpad': typeof ColumnsLayoutLaunchpadLazyRoute
|
||||
'/columns/_layout/notification': typeof ColumnsLayoutNotificationLazyRoute
|
||||
'/columns/_layout/onboarding': typeof ColumnsLayoutOnboardingLazyRoute
|
||||
@@ -871,7 +871,6 @@ export interface FileRouteTypes {
|
||||
| '/auth/import'
|
||||
| '/auth/new'
|
||||
| '/editor'
|
||||
| '/$account/home'
|
||||
| '/$account/bitcoin-connect'
|
||||
| '/$account/general'
|
||||
| '/$account/profile'
|
||||
@@ -881,6 +880,7 @@ export interface FileRouteTypes {
|
||||
| '/columns/global'
|
||||
| '/columns/newsfeed'
|
||||
| '/columns/stories'
|
||||
| '/$account/home'
|
||||
| '/columns/launchpad'
|
||||
| '/columns/notification'
|
||||
| '/columns/onboarding'
|
||||
@@ -910,7 +910,6 @@ export interface FileRouteTypes {
|
||||
| '/auth/import'
|
||||
| '/auth/new'
|
||||
| '/editor'
|
||||
| '/$account/home'
|
||||
| '/$account/bitcoin-connect'
|
||||
| '/$account/general'
|
||||
| '/$account/profile'
|
||||
@@ -920,6 +919,7 @@ export interface FileRouteTypes {
|
||||
| '/columns/global'
|
||||
| '/columns/newsfeed'
|
||||
| '/columns/stories'
|
||||
| '/$account/home'
|
||||
| '/columns/launchpad'
|
||||
| '/columns/notification'
|
||||
| '/columns/onboarding'
|
||||
@@ -952,7 +952,6 @@ export interface FileRouteTypes {
|
||||
| '/auth/import'
|
||||
| '/auth/new'
|
||||
| '/editor/'
|
||||
| '/$account/_app/home'
|
||||
| '/$account/_settings/bitcoin-connect'
|
||||
| '/$account/_settings/general'
|
||||
| '/$account/_settings/profile'
|
||||
@@ -962,6 +961,7 @@ export interface FileRouteTypes {
|
||||
| '/columns/_layout/global'
|
||||
| '/columns/_layout/newsfeed'
|
||||
| '/columns/_layout/stories'
|
||||
| '/$account/_app/home'
|
||||
| '/columns/_layout/launchpad'
|
||||
| '/columns/_layout/notification'
|
||||
| '/columns/_layout/onboarding'
|
||||
@@ -1131,10 +1131,6 @@ export const routeTree = rootRoute
|
||||
"/editor/": {
|
||||
"filePath": "editor/index.tsx"
|
||||
},
|
||||
"/$account/_app/home": {
|
||||
"filePath": "$account/_app/home.tsx",
|
||||
"parent": "/$account/_app"
|
||||
},
|
||||
"/$account/_settings/bitcoin-connect": {
|
||||
"filePath": "$account/_settings/bitcoin-connect.tsx",
|
||||
"parent": "/$account/_settings"
|
||||
@@ -1175,6 +1171,10 @@ export const routeTree = rootRoute
|
||||
"filePath": "columns/_layout/stories.tsx",
|
||||
"parent": "/columns/_layout"
|
||||
},
|
||||
"/$account/_app/home": {
|
||||
"filePath": "$account/_app.home.lazy.tsx",
|
||||
"parent": "/$account/_app"
|
||||
},
|
||||
"/columns/_layout/launchpad": {
|
||||
"filePath": "columns/_layout/launchpad.lazy.tsx",
|
||||
"parent": "/columns/_layout"
|
||||
|
||||
@@ -45,16 +45,16 @@ function Screen() {
|
||||
}, [emblaApi]);
|
||||
|
||||
const emitScrollEvent = useCallback(() => {
|
||||
getCurrentWindow().emit("child_webview", { scroll: true });
|
||||
}, []);
|
||||
|
||||
const emitResizeEvent = useCallback(() => {
|
||||
getCurrentWindow().emit("child_webview", { resize: true, direction: "x" });
|
||||
getCurrentWindow().emit("column_scroll", {});
|
||||
}, []);
|
||||
|
||||
const add = useDebouncedCallback((column: LumeColumn) => {
|
||||
column.label = `${column.label}-${nanoid()}`; // update col label
|
||||
appColumns.setState((prev) => [column, ...prev]);
|
||||
|
||||
if (emblaApi) {
|
||||
emblaApi.scrollTo(0, true);
|
||||
}
|
||||
}, 150);
|
||||
|
||||
const remove = useDebouncedCallback((label: string) => {
|
||||
@@ -112,16 +112,14 @@ function Screen() {
|
||||
useEffect(() => {
|
||||
if (emblaApi) {
|
||||
emblaApi.on("scroll", emitScrollEvent);
|
||||
emblaApi.on("resize", emitResizeEvent);
|
||||
emblaApi.on("slidesChanged", emitScrollEvent);
|
||||
}
|
||||
|
||||
return () => {
|
||||
emblaApi?.off("scroll", emitScrollEvent);
|
||||
emblaApi?.off("resize", emitResizeEvent);
|
||||
emblaApi?.off("slidesChanged", emitScrollEvent);
|
||||
};
|
||||
}, [emblaApi, emitScrollEvent, emitResizeEvent]);
|
||||
}, [emblaApi, emitScrollEvent]);
|
||||
|
||||
// Listen for keyboard event
|
||||
useEffect(() => {
|
||||
@@ -1,3 +0,0 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/$account/_app/home")();
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from "./event";
|
||||
export * from "./window";
|
||||
export * from "./hooks/useEvent";
|
||||
export * from "./hooks/useProfile";
|
||||
export * from "./useEvent";
|
||||
export * from "./useProfile";
|
||||
export * from "./useRect";
|
||||
|
||||
@@ -2,7 +2,7 @@ import { type Result, type RichEvent, commands } from "@/commands.gen";
|
||||
import type { NostrEvent } from "@/types";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { nip19 } from "nostr-tools";
|
||||
import { LumeEvent } from "../event";
|
||||
import { LumeEvent } from "./event";
|
||||
|
||||
export function useEvent(id: string, repost?: string) {
|
||||
const { isLoading, isError, error, data } = useQuery({
|
||||
53
src/system/useRect.ts
Normal file
53
src/system/useRect.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
type MutableRefObject<T> = {
|
||||
current: T;
|
||||
};
|
||||
|
||||
const useEffectInEvent = <K extends keyof WindowEventMap>(
|
||||
event: K,
|
||||
set: () => void,
|
||||
useCapture?: boolean,
|
||||
) => {
|
||||
useEffect(() => {
|
||||
if (set) {
|
||||
set();
|
||||
window.addEventListener(event, set, useCapture);
|
||||
|
||||
return () => window.removeEventListener(event, set, useCapture);
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
const useTauriInEvent = (set: () => void) => {
|
||||
useEffect(() => {
|
||||
if (set) {
|
||||
const unlisten = listen("column_scroll", () => {
|
||||
set();
|
||||
});
|
||||
|
||||
return () => {
|
||||
unlisten.then((f) => f());
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const useRect = <T extends HTMLDivElement | null>(): [
|
||||
DOMRect | undefined,
|
||||
MutableRefObject<T | null>,
|
||||
] => {
|
||||
const ref = useRef<T>(null);
|
||||
const [rect, setRect] = useState<DOMRect>();
|
||||
|
||||
const set = (): void => {
|
||||
setRect(ref.current?.getBoundingClientRect());
|
||||
};
|
||||
|
||||
useTauriInEvent(set);
|
||||
useEffectInEvent("resize", set);
|
||||
useEffectInEvent("scroll", set, true);
|
||||
|
||||
return [rect, ref];
|
||||
};
|
||||
Reference in New Issue
Block a user