From 0f4309659afe4d68dd250998b77f44c51fc52fd5 Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 21 Nov 2025 21:52:37 +0700 Subject: [PATCH] [WEB-5478] chore: fix types (#8155) --- .../core/components/instance/setup-form.tsx | 3 +- .../issues/issue-layouts/kanban/block.tsx | 2 - .../(projects)/analytics/[tabId]/page.tsx | 5 +- .../components/cycles/active-cycle/root.tsx | 132 ++++++---- .../components/comments/quick-actions.tsx | 9 +- .../components/common/breadcrumb-link.tsx | 2 - .../core/multiple-select/select-group.tsx | 2 - .../cycles/active-cycle/cycle-stats.tsx | 2 +- .../issue-layouts/calendar/issue-block.tsx | 2 +- .../issues/issue-layouts/kanban/block.tsx | 2 - .../issue-layouts/properties/labels.tsx | 240 +++++++++++------- .../labels/create-update-label-inline.tsx | 5 +- .../core/components/onboarding/steps/root.tsx | 40 +-- .../components/pages/dropdowns/actions.tsx | 21 +- .../pages/editor/toolbar/options-dropdown.tsx | 19 +- .../components/pages/loaders/page-loader.tsx | 4 +- .../project-states/create-update/form.tsx | 26 +- .../core/components/sidebar/sidebar-item.tsx | 2 +- .../components/ui/markdown-to-component.tsx | 12 +- .../core/hooks/use-realtime-page-events.tsx | 29 ++- package.json | 5 +- packages/propel/src/dialog/root.tsx | 19 +- packages/propel/src/popover/root.tsx | 16 +- packages/propel/src/skeleton/root.tsx | 2 +- packages/types/package.json | 1 + .../src/breadcrumbs/navigation-dropdown.tsx | 4 +- pnpm-lock.yaml | 3 + 27 files changed, 369 insertions(+), 240 deletions(-) diff --git a/apps/admin/core/components/instance/setup-form.tsx b/apps/admin/core/components/instance/setup-form.tsx index dc67b7c0d..ab25b1a3e 100644 --- a/apps/admin/core/components/instance/setup-form.tsx +++ b/apps/admin/core/components/instance/setup-form.tsx @@ -51,8 +51,7 @@ const defaultFromData: TFormData = { is_telemetry_enabled: true, }; -export function InstanceSetupForm(props) { - const {} = props; +export function InstanceSetupForm() { // search params const searchParams = useSearchParams(); const firstNameParam = searchParams.get("first_name") || undefined; diff --git a/apps/space/core/components/issues/issue-layouts/kanban/block.tsx b/apps/space/core/components/issues/issue-layouts/kanban/block.tsx index 0d7db0003..8e5a757aa 100644 --- a/apps/space/core/components/issues/issue-layouts/kanban/block.tsx +++ b/apps/space/core/components/issues/issue-layouts/kanban/block.tsx @@ -104,5 +104,3 @@ export const KanbanIssueBlock = observer(function KanbanIssueBlock(props: IssueB ); }); - -KanbanIssueBlock.displayName = "KanbanIssueBlock"; diff --git a/apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/page.tsx index 03c841605..13e5177d6 100644 --- a/apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/page.tsx +++ b/apps/web/app/(all)/[workspaceSlug]/(projects)/analytics/[tabId]/page.tsx @@ -5,6 +5,7 @@ import { useRouter } from "next/navigation"; import { EUserPermissions, EUserPermissionsLevel, PROJECT_TRACKER_ELEMENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { EmptyStateDetailed } from "@plane/propel/empty-state"; +import type { AnalyticsTab } from "@plane/types"; import { Tabs } from "@plane/ui"; import type { TabItem } from "@plane/ui"; // components @@ -44,9 +45,7 @@ function AnalyticsPage({ params }: Route.ComponentProps) { const pageTitle = currentWorkspace?.name ? t(`workspace_analytics.page_label`, { workspace: currentWorkspace?.name }) : undefined; - const ANALYTICS_TABS = useMemo(function ANALYTICS_TABS() { - return getAnalyticsTabs(t); - }); + const ANALYTICS_TABS = useMemo(() => getAnalyticsTabs(t), [t]); const tabs: TabItem[] = useMemo( () => ANALYTICS_TABS.map((tab) => ({ diff --git a/apps/web/ce/components/cycles/active-cycle/root.tsx b/apps/web/ce/components/cycles/active-cycle/root.tsx index f55d7b6e0..12e395fba 100644 --- a/apps/web/ce/components/cycles/active-cycle/root.tsx +++ b/apps/web/ce/components/cycles/active-cycle/root.tsx @@ -1,9 +1,9 @@ -import { useMemo } from "react"; import { observer } from "mobx-react"; import { useTheme } from "next-themes"; import { Disclosure } from "@headlessui/react"; // plane imports import { useTranslation } from "@plane/i18n"; +import type { ICycle } from "@plane/types"; import { Row } from "@plane/ui"; // assets import darkActiveCycleAsset from "@/app/assets/empty-state/cycle/active-dark.webp?url"; @@ -27,6 +27,69 @@ interface IActiveCycleDetails { showHeader?: boolean; } +type ActiveCyclesComponentProps = { + cycleId: string | null | undefined; + activeCycle: ICycle | null; + activeCycleResolvedPath: string; + workspaceSlug: string; + projectId: string; + handleFiltersUpdate: (filters: any) => void; + cycleIssueDetails?: ActiveCycleIssueDetails | { nextPageResults: boolean }; +}; + +const ActiveCyclesComponent = observer(function ActiveCyclesComponent({ + cycleId, + activeCycle, + activeCycleResolvedPath, + workspaceSlug, + projectId, + handleFiltersUpdate, + cycleIssueDetails, +}: ActiveCyclesComponentProps) { + const { t } = useTranslation(); + + if (!cycleId || !activeCycle) { + return ( + + ); + } + + return ( +
+ + +
+ + + +
+
+
+ ); +}); + export const ActiveCycleRoot = observer(function ActiveCycleRoot(props: IActiveCycleDetails) { const { workspaceSlug, projectId, cycleId: propsCycleId, showHeader = true } = props; // theme hook @@ -45,51 +108,6 @@ export const ActiveCycleRoot = observer(function ActiveCycleRoot(props: IActiveC cycleIssueDetails, } = useCyclesDetails({ workspaceSlug, projectId, cycleId }); - const ActiveCyclesComponent = useMemo(function ActiveCyclesComponent() { - return ( - <> - {!cycleId || !activeCycle ? ( - - ) : ( -
- {cycleId && ( - - )} - -
- - - -
-
-
- )} - - ); - }); - return ( <> {showHeader ? ( @@ -99,12 +117,30 @@ export const ActiveCycleRoot = observer(function ActiveCycleRoot(props: IActiveC - {ActiveCyclesComponent} + + + )} ) : ( - <>{ActiveCyclesComponent} + )} ); diff --git a/apps/web/core/components/comments/quick-actions.tsx b/apps/web/core/components/comments/quick-actions.tsx index 32c6786b1..b865fe78d 100644 --- a/apps/web/core/components/comments/quick-actions.tsx +++ b/apps/web/core/components/comments/quick-actions.tsx @@ -31,8 +31,8 @@ export const CommentQuickActions = observer(function CommentQuickActions(props: // translation const { t } = useTranslation(); - const MENU_ITEMS = useMemo(function MENU_ITEMS() { - return [ + const MENU_ITEMS = useMemo( + () => [ { key: "edit", action: setEditMode, @@ -70,8 +70,9 @@ export const CommentQuickActions = observer(function CommentQuickActions(props: icon: Trash2, shouldRender: canDelete, }, - ]; - }); + ], + [t, setEditMode, canEdit, showCopyLinkOption, activityOperations, comment, showAccessSpecifier, canDelete] + ); return ( diff --git a/apps/web/core/components/common/breadcrumb-link.tsx b/apps/web/core/components/common/breadcrumb-link.tsx index ba523f5fe..254311b82 100644 --- a/apps/web/core/components/common/breadcrumb-link.tsx +++ b/apps/web/core/components/common/breadcrumb-link.tsx @@ -79,5 +79,3 @@ export const BreadcrumbLink = observer(function BreadcrumbLink(props: Props) { return {content}; }); - -BreadcrumbLink.displayName = "BreadcrumbLink"; diff --git a/apps/web/core/components/core/multiple-select/select-group.tsx b/apps/web/core/components/core/multiple-select/select-group.tsx index 3e1d4da6b..c23ee07ee 100644 --- a/apps/web/core/components/core/multiple-select/select-group.tsx +++ b/apps/web/core/components/core/multiple-select/select-group.tsx @@ -21,5 +21,3 @@ export const MultipleSelectGroup = observer(function MultipleSelectGroup(props: return <>{children(helpers)}; }); - -MultipleSelectGroup.displayName = "MultipleSelectGroup"; diff --git a/apps/web/core/components/cycles/active-cycle/cycle-stats.tsx b/apps/web/core/components/cycles/active-cycle/cycle-stats.tsx index 8b8badf8c..57e70e2b2 100644 --- a/apps/web/core/components/cycles/active-cycle/cycle-stats.tsx +++ b/apps/web/core/components/cycles/active-cycle/cycle-stats.tsx @@ -44,7 +44,7 @@ export type ActiveCycleStatsProps = { cycle: ICycle | null; cycleId?: string | null; handleFiltersUpdate: (conditions: TWorkItemFilterCondition[]) => void; - cycleIssueDetails: ActiveCycleIssueDetails; + cycleIssueDetails?: ActiveCycleIssueDetails | { nextPageResults: boolean }; }; export const ActiveCycleStats = observer(function ActiveCycleStats(props: ActiveCycleStatsProps) { diff --git a/apps/web/core/components/issues/issue-layouts/calendar/issue-block.tsx b/apps/web/core/components/issues/issue-layouts/calendar/issue-block.tsx index 43fbbe688..69a457907 100644 --- a/apps/web/core/components/issues/issue-layouts/calendar/issue-block.tsx +++ b/apps/web/core/components/issues/issue-layouts/calendar/issue-block.tsx @@ -32,7 +32,7 @@ type Props = { }; export const CalendarIssueBlock = observer( - forwardRef((props, ref) => { + forwardRef(function CalendarIssueBlock(props: Props, ref: React.ForwardedRef) { const { issue, quickActions, isDragging = false, isEpic = false } = props; // states const [isMenuActive, setIsMenuActive] = useState(false); diff --git a/apps/web/core/components/issues/issue-layouts/kanban/block.tsx b/apps/web/core/components/issues/issue-layouts/kanban/block.tsx index b93e057ad..35e9e1b77 100644 --- a/apps/web/core/components/issues/issue-layouts/kanban/block.tsx +++ b/apps/web/core/components/issues/issue-layouts/kanban/block.tsx @@ -299,5 +299,3 @@ export const KanbanIssueBlock = observer(function KanbanIssueBlock(props: IssueB ); }); - -KanbanIssueBlock.displayName = "KanbanIssueBlock"; diff --git a/apps/web/core/components/issues/issue-layouts/properties/labels.tsx b/apps/web/core/components/issues/issue-layouts/properties/labels.tsx index 2ebff3686..0a7cf045e 100644 --- a/apps/web/core/components/issues/issue-layouts/properties/labels.tsx +++ b/apps/web/core/components/issues/issue-layouts/properties/labels.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import type { Placement } from "@popperjs/core"; import { observer } from "mobx-react"; // plane helpers @@ -36,6 +36,126 @@ export interface IIssuePropertyLabels { fullHeight?: boolean; } +type NoLabelProps = { + isMobile: boolean; + noLabelBorder: boolean; + fullWidth: boolean; + placeholderText?: string; +}; + +const NoLabel = observer(function NoLabel({ isMobile, noLabelBorder, fullWidth, placeholderText }: NoLabelProps) { + const { t } = useTranslation(); + + return ( + +
+ + {placeholderText} +
+
+ ); +}); + +type LabelSummaryProps = { + isMobile: boolean; + fullWidth: boolean; + noLabelBorder: boolean; + disabled?: boolean; + projectLabels: IIssueLabel[]; + value: string[]; +}; + +function LabelSummary({ isMobile, fullWidth, noLabelBorder, disabled, projectLabels, value }: LabelSummaryProps) { + const { t } = useTranslation(); + return ( +
+ value.includes(l?.id)) + .map((l) => l?.name) + .join(", ")} + renderByDefault={false} + > +
+ + {`${value.length} Labels`} +
+
+
+ ); +} + +type LabelItemProps = { + label: IIssueLabel; + isMobile: boolean; + renderByDefault: boolean; + disabled?: boolean; + fullWidth: boolean; + noLabelBorder: boolean; +}; + +const LabelItem = observer(function LabelItem({ + label, + isMobile, + renderByDefault, + disabled, + fullWidth, + noLabelBorder, +}: LabelItemProps) { + const { t } = useTranslation(); + + return ( + +
+
+ +
{label?.name}
+
+
+
+ ); +}); + export const IssuePropertyLabels = observer(function IssuePropertyLabels(props: IIssuePropertyLabels) { const { projectId, @@ -54,8 +174,6 @@ export const IssuePropertyLabels = observer(function IssuePropertyLabels(props: fullWidth = false, fullHeight = false, } = props; - // i18n - const { t } = useTranslation(); // states const [isOpen, setIsOpen] = useState(false); // refs @@ -83,91 +201,6 @@ export const IssuePropertyLabels = observer(function IssuePropertyLabels(props: let projectLabels: IIssueLabel[] = defaultOptions as IIssueLabel[]; if (storeLabels && storeLabels.length > 0) projectLabels = storeLabels; - const NoLabel = useMemo(function NoLabel() { - return ( - -
- - {placeholderText} -
-
- ); - }); - - const LabelSummary = useMemo(function LabelSummary() { - return ( -
- value.includes(l?.id)) - .map((l) => l?.name) - .join(", ")} - renderByDefault={false} - > -
- - {`${value.length} Labels`} -
-
-
- ); - }); - - const LabelItem = useCallback(function LabelItem({ label }: { label: IIssueLabel }) { - return ( - -
-
- -
{label?.name}
-
-
-
- ); - }); - return ( <> {value.length > 0 ? ( @@ -185,7 +218,16 @@ export const IssuePropertyLabels = observer(function IssuePropertyLabels(props: hideDropdownArrow={hideDropdownArrow} fullWidth={fullWidth} fullHeight={fullHeight} - label={} + label={ + + } /> )) ) : ( @@ -198,7 +240,16 @@ export const IssuePropertyLabels = observer(function IssuePropertyLabels(props: placement={placement} fullWidth={fullWidth} fullHeight={fullHeight} - label={LabelSummary} + label={ + + } /> ) ) : ( @@ -211,7 +262,14 @@ export const IssuePropertyLabels = observer(function IssuePropertyLabels(props: placement={placement} fullWidth={fullWidth} fullHeight={fullHeight} - label={NoLabel} + label={ + + } /> )} diff --git a/apps/web/core/components/labels/create-update-label-inline.tsx b/apps/web/core/components/labels/create-update-label-inline.tsx index 67d3e8557..e391ac4ea 100644 --- a/apps/web/core/components/labels/create-update-label-inline.tsx +++ b/apps/web/core/components/labels/create-update-label-inline.tsx @@ -33,7 +33,10 @@ const defaultValues: Partial = { }; export const CreateUpdateLabelInline = observer( - forwardRef(function CreateUpdateLabelInline(props, ref) { + forwardRef(function CreateUpdateLabelInline( + props: TCreateUpdateLabelInlineProps, + ref: React.ForwardedRef + ) { const { labelForm, setLabelForm, isUpdating, labelOperationsCallbacks, labelToUpdate, onClose } = props; // form info const { diff --git a/apps/web/core/components/onboarding/steps/root.tsx b/apps/web/core/components/onboarding/steps/root.tsx index 966975711..f4941eafa 100644 --- a/apps/web/core/components/onboarding/steps/root.tsx +++ b/apps/web/core/components/onboarding/steps/root.tsx @@ -1,5 +1,4 @@ -import type { FC } from "react"; -import { useEffect, useMemo, useRef } from "react"; +import { useEffect, useRef } from "react"; // plane imports import type { IWorkspaceMemberInvitation } from "@plane/types"; import { EOnboardingSteps } from "@plane/types"; @@ -16,8 +15,25 @@ type Props = { handleStepChange: (step: EOnboardingSteps, skipInvites?: boolean) => void; }; +function OnboardingStepContent({ currentStep, invitations, handleStepChange }: Props) { + switch (currentStep) { + case EOnboardingSteps.PROFILE_SETUP: + return ; + case EOnboardingSteps.ROLE_SETUP: + return ; + case EOnboardingSteps.USE_CASE_SETUP: + return ; + case EOnboardingSteps.WORKSPACE_CREATE_OR_JOIN: + return ; + case EOnboardingSteps.INVITE_MEMBERS: + return ; + default: + return null; + } +} + export function OnboardingStepRoot(props: Props) { - const { currentStep, invitations, handleStepChange } = props; + const { currentStep } = props; // ref for the scrollable container const scrollContainerRef = useRef(null); @@ -31,24 +47,12 @@ export function OnboardingStepRoot(props: Props) { } }, [currentStep]); - // memoized step component mapping - const stepComponents = useMemo( - () => ({ - [EOnboardingSteps.PROFILE_SETUP]: , - [EOnboardingSteps.ROLE_SETUP]: , - [EOnboardingSteps.USE_CASE_SETUP]: , - [EOnboardingSteps.WORKSPACE_CREATE_OR_JOIN]: ( - - ), - [EOnboardingSteps.INVITE_MEMBERS]: , - }), - [handleStepChange, invitations] - ); - return (
-
{stepComponents[currentStep]}
+
+ +
); diff --git a/apps/web/core/components/pages/dropdowns/actions.tsx b/apps/web/core/components/pages/dropdowns/actions.tsx index f234dd223..2bbc5b202 100644 --- a/apps/web/core/components/pages/dropdowns/actions.tsx +++ b/apps/web/core/components/pages/dropdowns/actions.tsx @@ -87,7 +87,7 @@ export const PageActions = observer(function PageActions(props: Props) { canCurrentUserMovePage, } = page; // menu items - const MENU_ITEMS = useMemo(function MENU_ITEMS() { + const MENU_ITEMS = useMemo(() => { const menuItems: (TContextMenuItem & { key: TPageActions })[] = [ { key: "toggle-lock", @@ -175,13 +175,26 @@ export const PageActions = observer(function PageActions(props: Props) { menuItems.push(...extraOptions); } return menuItems; - }); + }, [ + extraOptions, + is_locked, + canCurrentUserLockPage, + access, + canCurrentUserChangeAccess, + archived_at, + canCurrentUserDuplicatePage, + canCurrentUserArchivePage, + canCurrentUserDeletePage, + canCurrentUserMovePage, + isMovePageEnabled, + pageOperations, + ]); // arrange options - const arrangedOptions = useMemo( + const arrangedOptions = useMemo<(TContextMenuItem & { key: TPageActions })[]>( () => optionsOrder .map((key) => MENU_ITEMS.find((item) => item.key === key)) - .filter((item) => !!item) as (TContextMenuItem & { key: TPageActions })[], + .filter((item): item is TContextMenuItem & { key: TPageActions } => !!item), [optionsOrder, MENU_ITEMS] ); diff --git a/apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx b/apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx index 1b4e38c76..0eca248c7 100644 --- a/apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx +++ b/apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx @@ -43,8 +43,8 @@ export const PageOptionsDropdown = observer(function PageOptionsDropdown(props: // query params const { updateQueryParams } = useQueryParams(); // menu items list - const EXTRA_MENU_OPTIONS = useMemo(function EXTRA_MENU_OPTIONS() { - return [ + const EXTRA_MENU_OPTIONS = useMemo<(TContextMenuItem & { key: TPageActions })[]>( + () => [ { key: "full-screen", action: () => handleFullWidth(!isFullWidth), @@ -106,8 +106,19 @@ export const PageOptionsDropdown = observer(function PageOptionsDropdown(props: icon: ArrowUpToLine, shouldRender: true, }, - ]; - }); + ], + [ + handleFullWidth, + isFullWidth, + handleStickyToolbar, + isStickyToolbarEnabled, + isContentEditable, + editorRef, + updateQueryParams, + router, + setIsExportModalOpen, + ] + ); return ( <> diff --git a/apps/web/core/components/pages/loaders/page-loader.tsx b/apps/web/core/components/pages/loaders/page-loader.tsx index 00ceb34e8..b55aeff42 100644 --- a/apps/web/core/components/pages/loaders/page-loader.tsx +++ b/apps/web/core/components/pages/loaders/page-loader.tsx @@ -1,9 +1,7 @@ import { range } from "lodash-es"; import { Loader } from "@plane/ui"; -export function PageLoader(props) { - const {} = props; - +export function PageLoader() { return (
diff --git a/apps/web/core/components/project-states/create-update/form.tsx b/apps/web/core/components/project-states/create-update/form.tsx index a7f763a76..2831b6d8f 100644 --- a/apps/web/core/components/project-states/create-update/form.tsx +++ b/apps/web/core/components/project-states/create-update/form.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState, useMemo } from "react"; +import { useEffect, useState } from "react"; import { TwitterPicker } from "react-color"; import { Button } from "@plane/propel/button"; import type { IState } from "@plane/types"; @@ -12,6 +12,17 @@ type TStateForm = { buttonTitle: string; }; +function PopoverButton({ color }: { color?: string }) { + return ( +
+ ); +} + export function StateForm(props: TStateForm) { const { data, onSubmit, onCancel, buttonDisabled, buttonTitle } = props; // states @@ -45,22 +56,11 @@ export function StateForm(props: TStateForm) { } }; - const PopoverButton = useMemo(function PopoverButton() { - return ( -
- ); - }); - return (
{/* color */}
- + } panelClassName="mt-4 -ml-3"> handleFormData("color", value.hex)} />
diff --git a/apps/web/core/components/sidebar/sidebar-item.tsx b/apps/web/core/components/sidebar/sidebar-item.tsx index dcb1f51eb..970b84fda 100644 --- a/apps/web/core/components/sidebar/sidebar-item.tsx +++ b/apps/web/core/components/sidebar/sidebar-item.tsx @@ -119,7 +119,7 @@ export type AppSidebarItemComponent = React.FC & { Button: React.FC; }; -function AppSidebarItem({ variant = "link", item }) { +function AppSidebarItem({ variant = "link", item }: AppSidebarItemProps) { if (!item) return null; const { icon, isActive, label, href, onClick, disabled } = item; diff --git a/apps/web/core/components/ui/markdown-to-component.tsx b/apps/web/core/components/ui/markdown-to-component.tsx index bd5198d64..fc2fd6f31 100644 --- a/apps/web/core/components/ui/markdown-to-component.tsx +++ b/apps/web/core/components/ui/markdown-to-component.tsx @@ -33,27 +33,27 @@ interface Props { options?: any; } -function HeadingPrimary({ children }) { +function HeadingPrimary({ children }: { children: React.ReactNode }) { return

{children}

; } -function HeadingSecondary({ children }) { +function HeadingSecondary({ children }: { children: React.ReactNode }) { return

{children}

; } -function Paragraph({ children }) { +function Paragraph({ children }: { children: React.ReactNode }) { return

{children}

; } -function OrderedList({ children }) { +function OrderedList({ children }: { children: React.ReactNode }) { return
    {children}
; } -function UnorderedList({ children }) { +function UnorderedList({ children }: { children: React.ReactNode }) { return
    {children}
; } -function Link({ href, children }) { +function Link({ href, children }: CustomComponentProps) { return ( {children} diff --git a/apps/web/core/hooks/use-realtime-page-events.tsx b/apps/web/core/hooks/use-realtime-page-events.tsx index 452fe0c64..16b144818 100644 --- a/apps/web/core/hooks/use-realtime-page-events.tsx +++ b/apps/web/core/hooks/use-realtime-page-events.tsx @@ -60,51 +60,51 @@ export const useRealtimePageEvents = ({ [getUserDetails] ); - const ACTION_HANDLERS = useMemo(function ACTION_HANDLERS() { - return { - archived: ({ pageIds, data }) => { + const ACTION_HANDLERS = useMemo( + () => ({ + archived: ({ pageIds, data }: { pageIds: string[]; data: EventToPayloadMap["archived"] }) => { pageIds.forEach((pageId) => { const pageItem = getPageById(pageId); if (pageItem) pageItem.archive({ archived_at: data.archived_at, shouldSync: false }); }); }, - unarchived: ({ pageIds }) => { + unarchived: ({ pageIds }: { pageIds: string[] }) => { pageIds.forEach((pageId) => { const pageItem = getPageById(pageId); if (pageItem) pageItem.restore({ shouldSync: false }); }); }, - locked: ({ pageIds }) => { + locked: ({ pageIds }: { pageIds: string[] }) => { pageIds.forEach((pageId) => { const pageItem = getPageById(pageId); if (pageItem) pageItem.lock({ shouldSync: false, recursive: false }); }); }, - unlocked: ({ pageIds }) => { + unlocked: ({ pageIds }: { pageIds: string[] }) => { pageIds.forEach((pageId) => { const pageItem = getPageById(pageId); if (pageItem) pageItem.unlock({ shouldSync: false, recursive: false }); }); }, - "made-public": ({ pageIds }) => { + "made-public": ({ pageIds }: { pageIds: string[] }) => { pageIds.forEach((pageId) => { const pageItem = getPageById(pageId); if (pageItem) pageItem.makePublic({ shouldSync: false }); }); }, - "made-private": ({ pageIds }) => { + "made-private": ({ pageIds }: { pageIds: string[] }) => { pageIds.forEach((pageId) => { const pageItem = getPageById(pageId); if (pageItem) pageItem.makePrivate({ shouldSync: false }); }); }, - deleted: ({ pageIds, data }) => { + deleted: ({ pageIds, data }: { pageIds: string[]; data: EventToPayloadMap["deleted"] }) => { pageIds.forEach((pageId) => { const pageItem = getPageById(pageId); if (pageItem) { @@ -123,7 +123,7 @@ export const useRealtimePageEvents = ({ }); }, - property_updated: ({ pageIds, data }) => { + property_updated: ({ pageIds, data }: { pageIds: string[]; data: EventToPayloadMap["property_updated"] }) => { pageIds.forEach((pageId) => { const pageInstance = getPageById(pageId); const { name: updatedName, ...rest } = data; @@ -132,7 +132,7 @@ export const useRealtimePageEvents = ({ }); }, - error: ({ pageIds, data }) => { + error: ({ pageIds, data }: { pageIds: string[]; data: EventToPayloadMap["error"] }) => { const errorType = data.error_type; const errorMessage = data.error_message || "An error occurred"; const errorCode = data.error_code; @@ -164,8 +164,9 @@ export const useRealtimePageEvents = ({ }, ...customRealtimeEventHandlers, - }; - }); + }), + [getPageById, removePage, page, currentUser, getUserDisplayText, router, handlers, customRealtimeEventHandlers] + ); // The main function that will be returned from this hook const updatePageProperties = useCallback( @@ -181,7 +182,7 @@ export const useRealtimePageEvents = ({ if (normalizedPageIds.length === 0) return; // Get the handler for this message type - const handler = ACTION_HANDLERS[actionType]; + const handler = ACTION_HANDLERS[actionType] as PageUpdateHandler | undefined; if (handler) { // Now TypeScript knows that handler and data match in type diff --git a/package.json b/package.json index b047a2e7d..7cd4ff824 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "fix:format": "turbo run fix:format", "check": "turbo run check", "check:lint": "turbo run check:lint", - "check:format": "turbo run check:format" + "check:format": "turbo run check:format", + "check:types": "turbo run check:types" }, "devDependencies": { "@prettier/plugin-oxc": "0.0.4", @@ -50,4 +51,4 @@ "engines": { "node": ">=22.18.0" } -} +} \ No newline at end of file diff --git a/packages/propel/src/dialog/root.tsx b/packages/propel/src/dialog/root.tsx index 018a3418a..e0a518b22 100644 --- a/packages/propel/src/dialog/root.tsx +++ b/packages/propel/src/dialog/root.tsx @@ -45,7 +45,10 @@ const getPositionClassNames = (position: DialogPosition) => "top-8 left-1/2 -translate-x-1/2": position === "top", }); -const DialogPortal = memo(function DialogPortal({ children, ...props }) { +const DialogPortal = memo(function DialogPortal({ + children, + ...props +}: React.ComponentProps) { return ( {children} @@ -54,12 +57,15 @@ const DialogPortal = memo(function DialogPortal({ children, ...props }) { }); DialogPortal.displayName = "DialogPortal"; -const DialogOverlay = memo(function DialogOverlay({ className, ...props }) { +const DialogOverlay = memo(function DialogOverlay({ + className, + ...props +}: React.ComponentProps) { return ; }); DialogOverlay.displayName = "DialogOverlay"; -const DialogComponent = memo(function DialogComponent({ children, ...props }) { +const DialogComponent = memo(function DialogComponent({ children, ...props }: DialogProps) { return ( {children} @@ -68,7 +74,10 @@ const DialogComponent = memo(function DialogComponent({ children, ...props }) { }); DialogComponent.displayName = "Dialog"; -const DialogTrigger = memo(function DialogTrigger({ children, ...props }) { +const DialogTrigger = memo(function DialogTrigger({ + children, + ...props +}: React.ComponentProps) { return ( {children} @@ -100,7 +109,7 @@ const DialogPanel = forwardRef(function DialogPanel( }); DialogPanel.displayName = "DialogPanel"; -const DialogTitle = memo(function DialogTitle({ className, children, ...props }) { +const DialogTitle = memo(function DialogTitle({ className, children, ...props }: DialogTitleProps) { return ( { + const { finalSide, finalAlign } = useMemo(() => { if (placement) { const converted = convertPlacementToSideAndAlign(placement); return { finalSide: converted.side, finalAlign: converted.align }; @@ -45,21 +45,21 @@ const PopoverContent = React.memo(function PopoverContent({ }); // wrapper components -const PopoverTrigger = React.memo(function PopoverTrigger(props) { +const PopoverTrigger = memo(function PopoverTrigger(props: React.ComponentProps) { return ; }); -const PopoverPortal = React.memo(function PopoverPortal(props) { +const PopoverPortal = memo(function PopoverPortal(props: React.ComponentProps) { return ; }); -const PopoverPositioner = React.memo(function PopoverPositioner(props) { +const PopoverPositioner = memo(function PopoverPositioner(props: React.ComponentProps) { return ; }); // compound components const Popover = Object.assign( - React.memo>(function Popover(props) { + memo(function Popover(props: React.ComponentProps) { return ; }), { diff --git a/packages/propel/src/skeleton/root.tsx b/packages/propel/src/skeleton/root.tsx index bc899c24d..03bb61bd3 100644 --- a/packages/propel/src/skeleton/root.tsx +++ b/packages/propel/src/skeleton/root.tsx @@ -37,4 +37,4 @@ const Skeleton = Object.assign(SkeletonRoot, { Item: SkeletonItem }); SkeletonRoot.displayName = "plane-ui-skeleton"; SkeletonItem.displayName = "plane-ui-skeleton-item"; -export { Skeleton }; +export { Skeleton, SkeletonRoot, SkeletonItem }; diff --git a/packages/types/package.json b/packages/types/package.json index 1e12367a0..c1493ba0a 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -26,6 +26,7 @@ "@plane/eslint-config": "workspace:*", "@plane/typescript-config": "workspace:*", "@prettier/plugin-oxc": "0.0.4", + "@types/node": "catalog:", "@types/react": "catalog:", "@types/react-dom": "catalog:", "tsdown": "catalog:", diff --git a/packages/ui/src/breadcrumbs/navigation-dropdown.tsx b/packages/ui/src/breadcrumbs/navigation-dropdown.tsx index fd7f114db..5929ee162 100644 --- a/packages/ui/src/breadcrumbs/navigation-dropdown.tsx +++ b/packages/ui/src/breadcrumbs/navigation-dropdown.tsx @@ -29,7 +29,7 @@ export function BreadcrumbNavigationDropdown(props: TBreadcrumbNavigationDropdow function NavigationButton() { return ( - + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b66eb845..24aedd2f3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1330,6 +1330,9 @@ importers: '@prettier/plugin-oxc': specifier: 0.0.4 version: 0.0.4 + '@types/node': + specifier: 'catalog:' + version: 22.12.0 '@types/react': specifier: 'catalog:' version: 18.3.11