From 5ad0ab6095e516bfab75e3240c5c5171c02b7fae Mon Sep 17 00:00:00 2001 From: shailesh Date: Fri, 6 Mar 2026 14:03:07 +0545 Subject: [PATCH 01/10] chore: replace any in invitation form --- packages/form/src/types/index.ts | 6 ++---- packages/user/src/api/invitation/index.ts | 3 +-- .../components/Invitation/InvitationForm.tsx | 19 +++++++------------ .../components/Invitation/InvitationModal.tsx | 4 ++-- .../Invitation/InvitationsTable.tsx | 6 ++++-- packages/user/src/types/invitation.ts | 8 ++++++++ 6 files changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/form/src/types/index.ts b/packages/form/src/types/index.ts index 2d6dcf83a..4487ac0bc 100644 --- a/packages/form/src/types/index.ts +++ b/packages/form/src/types/index.ts @@ -34,11 +34,9 @@ interface CustomInputProperties { submitCount?: number; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type AdditionalFormSchema = Zod.ZodObject; +export type AdditionalFormSchema = Zod.ZodObject; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type AdditionalDefaultValues = Record; +export type AdditionalDefaultValues = Record; export type RenderAdditionalFormFields = ( formContext: typeof useFormContext, diff --git a/packages/user/src/api/invitation/index.ts b/packages/user/src/api/invitation/index.ts index 528434c09..8c87d781b 100644 --- a/packages/user/src/api/invitation/index.ts +++ b/packages/user/src/api/invitation/index.ts @@ -11,8 +11,7 @@ import { DeleteInvitationResponse } from "@/types/invitation"; import client from "../axios"; export const addInvitation = async ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - invitationData: any, + invitationData: Record, apiBaseUrl: string, ): Promise => { const response = await client(apiBaseUrl).post( diff --git a/packages/user/src/components/Invitation/InvitationForm.tsx b/packages/user/src/components/Invitation/InvitationForm.tsx index fb9df5c3b..2071fae33 100644 --- a/packages/user/src/components/Invitation/InvitationForm.tsx +++ b/packages/user/src/components/Invitation/InvitationForm.tsx @@ -20,6 +20,7 @@ import type { InvitationAppOption, InvitationRoleOption, InvitationExpiryDateField, + InvitationFormInput, } from "@/types"; interface Properties { @@ -28,8 +29,7 @@ interface Properties { expiryDateField?: InvitationExpiryDateField; onCancel?: () => void; onSubmitted?: (response: AddInvitationResponse) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - prepareData?: (rawFormData: any) => any; + prepareData?: (rawFormData: InvitationFormInput) => Record; roles?: InvitationRoleOption[]; } @@ -56,8 +56,7 @@ export const InvitationForm = ({ >({}); const getDefaultValues = useCallback(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let defaultValues: any = { email: "", role: undefined }; + let defaultValues: Record = { email: "", role: undefined }; let filteredRoles = roles; @@ -90,8 +89,7 @@ export const InvitationForm = ({ expiryDateField?.display, ]); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const getFormData = (data: any) => { + const getFormData = (data: InvitationFormInput) => { const parsedData: { email: string; role: string; @@ -147,8 +145,7 @@ export const InvitationForm = ({ } }, [error, errorParameters, t]); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const onSubmit = (data: any) => { + const onSubmit = (data: InvitationFormInput) => { setSubmitting(true); setError(null); @@ -163,8 +160,7 @@ export const InvitationForm = ({ onSubmitted(response); } }) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .catch((error: any) => { + .catch((error) => { const code = error?.response?.data?.code || SOMETHING_WRONG_ERROR; const selectedApp = apps?.find((app) => app.id === data.app)?.name; @@ -182,8 +178,7 @@ export const InvitationForm = ({ }); }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let InvitationFormSchema: Zod.ZodObject = zod.object({ + let InvitationFormSchema: Zod.AnyZodObject = zod.object({ email: emailSchema({ invalid: t("validation.messages.validEmail"), required: t("validation.messages.email"), diff --git a/packages/user/src/components/Invitation/InvitationModal.tsx b/packages/user/src/components/Invitation/InvitationModal.tsx index 945c5fd05..f8720ca33 100644 --- a/packages/user/src/components/Invitation/InvitationModal.tsx +++ b/packages/user/src/components/Invitation/InvitationModal.tsx @@ -10,6 +10,7 @@ import type { InvitationAppOption, InvitationRoleOption, InvitationExpiryDateField, + InvitationFormInput, } from "@/types"; interface Properties { @@ -18,8 +19,7 @@ interface Properties { expiryDateField?: InvitationExpiryDateField; invitationButtonOptions?: IButtonProperties; onSubmitted?: (response: AddInvitationResponse) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - prepareData?: (data: any) => any; + prepareData?: (data: InvitationFormInput) => Record; roles?: InvitationRoleOption[]; } diff --git a/packages/user/src/components/Invitation/InvitationsTable.tsx b/packages/user/src/components/Invitation/InvitationsTable.tsx index dc14efd78..c4e8e1408 100644 --- a/packages/user/src/components/Invitation/InvitationsTable.tsx +++ b/packages/user/src/components/Invitation/InvitationsTable.tsx @@ -30,6 +30,7 @@ import type { RevokeInvitationResponse, Invitation, UserType, + InvitationFormInput, } from "../../types"; type VisibleColumn = @@ -59,8 +60,9 @@ export type InvitationsTableProperties = Partial< onInvitationDeleted?: (response: DeleteInvitationResponse) => void; onInvitationResent?: (data: ResendInvitationResponse) => void; onInvitationRevoked?: (data: RevokeInvitationResponse) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - prepareInvitationData?: (data: any) => any; + prepareInvitationData?: ( + data: InvitationFormInput, + ) => Record; roleFilterOptions?: FilterOption[]; roles?: Array; showAppColumn?: boolean; diff --git a/packages/user/src/types/invitation.ts b/packages/user/src/types/invitation.ts index 79e9c14b0..aa5b93c8d 100644 --- a/packages/user/src/types/invitation.ts +++ b/packages/user/src/types/invitation.ts @@ -40,6 +40,14 @@ export interface InvitationExpiryDateField { mode: "calendar" | "input"; } +export interface InvitationFormInput { + email: string; + role: string; + app?: number; + expiresAt?: Date | null; + [key: string]: unknown; +} + export type AddInvitationResponse = Invitation | ErrorResponse; export type DeleteInvitationResponse = Invitation | ErrorResponse; From a60be8ec1e4985f357fe2974211417fa59415c91 Mon Sep 17 00:00:00 2001 From: shailesh Date: Fri, 6 Mar 2026 17:11:11 +0545 Subject: [PATCH 02/10] chore(user): replace any --- .../SocialLogin/AuthSocialLoginCallback.tsx | 12 ++++++++---- .../src/components/UsersTable/AllUsersTable.tsx | 12 ++++++------ .../user/src/components/UsersTable/UsersTable.tsx | 15 +++++++-------- .../UsersTable/useUserActionsMethods.ts | 14 ++++++-------- packages/user/src/hooks/useUserNavigationMenu.ts | 3 +-- .../user/src/layouts/UserEnabledHeaderLayout.tsx | 3 +-- .../layouts/UserEnabledSidebarHeaderLayout.tsx | 3 +-- .../src/layouts/UserEnabledSidebarOnlyLayout.tsx | 3 +-- packages/user/src/supertokens/change-email.ts | 12 ++++++++---- .../src/supertokens/profile-validation-claim.ts | 7 ++++--- packages/user/src/supertokens/superTokens.ts | 9 ++++++--- packages/user/src/types/invitation.ts | 8 ++++---- packages/user/src/views/AcceptInvitation.tsx | 10 ++++------ packages/user/src/views/SignupFirstUser.tsx | 3 +-- 14 files changed, 58 insertions(+), 56 deletions(-) diff --git a/packages/user/src/components/SocialLogin/AuthSocialLoginCallback.tsx b/packages/user/src/components/SocialLogin/AuthSocialLoginCallback.tsx index 2a085a76e..1d860bd3c 100644 --- a/packages/user/src/components/SocialLogin/AuthSocialLoginCallback.tsx +++ b/packages/user/src/components/SocialLogin/AuthSocialLoginCallback.tsx @@ -45,10 +45,14 @@ export const AuthSocialLoginCallback = () => { navigate(loginPath); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } catch (err: any) { - if (err.isSuperTokensGeneralError === true) { - toast.error(err.message); + } catch (error) { + const _error = error as { + isSuperTokensGeneralError?: boolean; + message?: string; + }; + + if (_error.isSuperTokensGeneralError === true) { + toast.error(_error.message); } else { toast.error(`${t("authSocialLoginCallback.message.error")}`); } diff --git a/packages/user/src/components/UsersTable/AllUsersTable.tsx b/packages/user/src/components/UsersTable/AllUsersTable.tsx index 690eafa0a..a5b112b32 100644 --- a/packages/user/src/components/UsersTable/AllUsersTable.tsx +++ b/packages/user/src/components/UsersTable/AllUsersTable.tsx @@ -18,6 +18,7 @@ import type { ResendInvitationResponse, RevokeInvitationResponse, ExtendedUser, + InvitationFormInput, } from "@/types"; type VisibleColumn = @@ -44,12 +45,11 @@ export type AllUsersTableProperties = Partial< onInvitationAdded?: (response: AddInvitationResponse) => void; onInvitationResent?: (data: ResendInvitationResponse) => void; onInvitationRevoked?: (data: RevokeInvitationResponse) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onUserDisabled?: (data: any) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onUserEnabled?: (data: any) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - prepareInvitationData?: (data: any) => any; + onUserDisabled?: (data: ExtendedUser) => void; + onUserEnabled?: (data: ExtendedUser) => void; + prepareInvitationData?: ( + data: InvitationFormInput, + ) => Record; roles?: Array; showInviteAction?: boolean; showAppColumn?: boolean; diff --git a/packages/user/src/components/UsersTable/UsersTable.tsx b/packages/user/src/components/UsersTable/UsersTable.tsx index 5d5fe529a..e35d59fa9 100644 --- a/packages/user/src/components/UsersTable/UsersTable.tsx +++ b/packages/user/src/components/UsersTable/UsersTable.tsx @@ -22,6 +22,7 @@ import type { InvitationRoleOption, InvitationExpiryDateField, UserType, + InvitationFormInput, } from "@/types"; type VisibleColumn = @@ -51,12 +52,11 @@ export type UsersTableProperties = Partial< invitationButtonOptions?: IButtonProperties; invitationExpiryDateField?: InvitationExpiryDateField; onInvitationAdded?: (response: AddInvitationResponse) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onUserEnabled?: (data: any) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onUserDisabled?: (data: any) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - prepareInvitationData?: (data: any) => any; + onUserEnabled?: (data: unknown) => void; + onUserDisabled?: (data: unknown) => void; + prepareInvitationData?: ( + data: InvitationFormInput, + ) => Record; roles?: Array; roleFilterOptions?: FilterOption[]; showInviteAction?: boolean; @@ -194,8 +194,7 @@ export const UsersTable = ({ return true; } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const updatedFilterValue = filterValue.map((value: any) => { + const updatedFilterValue = filterValue.map((value: unknown) => { switch (value) { case "true": return true; diff --git a/packages/user/src/components/UsersTable/useUserActionsMethods.ts b/packages/user/src/components/UsersTable/useUserActionsMethods.ts index 2e42d4e1f..cd1c843a4 100644 --- a/packages/user/src/components/UsersTable/useUserActionsMethods.ts +++ b/packages/user/src/components/UsersTable/useUserActionsMethods.ts @@ -1,6 +1,8 @@ import { useTranslation } from "@prefabs.tech/react-i18n"; import { toast } from "react-toastify"; +import { ExtendedUser } from "@/types"; + import { disableUser, enableUser } from "../../api/user"; import { useConfig } from "../../hooks"; @@ -8,17 +10,14 @@ export const useUserActions = ({ onUserDisabled, onUserEnabled, }: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onUserDisabled?: (response: any) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onUserEnabled?: (response: any) => void; + onUserDisabled?: (response: unknown) => void; + onUserEnabled?: (response: unknown) => void; }) => { const config = useConfig(); const { t } = useTranslation("users"); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handleDisableUser = (user: any) => { + const handleDisableUser = (user: ExtendedUser) => { disableUser(user.id, config.apiBaseUrl) .then((response) => { if ("data" in response && response.data.status === "OK") { @@ -36,8 +35,7 @@ export const useUserActions = ({ }); }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handleEnableUser = (user: any) => { + const handleEnableUser = (user: ExtendedUser) => { enableUser(user.id, config.apiBaseUrl) .then((response) => { if ("data" in response && response.data.status === "OK") { diff --git a/packages/user/src/hooks/useUserNavigationMenu.ts b/packages/user/src/hooks/useUserNavigationMenu.ts index 4bd839721..64a9ffd18 100644 --- a/packages/user/src/hooks/useUserNavigationMenu.ts +++ b/packages/user/src/hooks/useUserNavigationMenu.ts @@ -17,8 +17,7 @@ interface Properties { authNavigationMenu?: NavMenuItemType; addAuthNavigationMenu: boolean; userNavigationMenu?: NavMenuItemType; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onLogout?: () => Promise; + onLogout?: () => Promise; } export const useUserNavigationMenu = ({ diff --git a/packages/user/src/layouts/UserEnabledHeaderLayout.tsx b/packages/user/src/layouts/UserEnabledHeaderLayout.tsx index ba719ab31..4c65ad2a5 100644 --- a/packages/user/src/layouts/UserEnabledHeaderLayout.tsx +++ b/packages/user/src/layouts/UserEnabledHeaderLayout.tsx @@ -12,8 +12,7 @@ interface IProperties extends Omit< > { authNavigationMenu?: UserMenuType; userNavigationMenu?: UserMenuType; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onLogout?: () => Promise; + onLogout?: () => Promise; } export const UserEnabledHeaderLayout = ({ diff --git a/packages/user/src/layouts/UserEnabledSidebarHeaderLayout.tsx b/packages/user/src/layouts/UserEnabledSidebarHeaderLayout.tsx index 2df916c3d..a2b1d348c 100644 --- a/packages/user/src/layouts/UserEnabledSidebarHeaderLayout.tsx +++ b/packages/user/src/layouts/UserEnabledSidebarHeaderLayout.tsx @@ -11,8 +11,7 @@ import { useUserNavigationMenu } from ".."; interface Properties extends SidebarHeaderLayoutProperties { authNavigationMenu?: UserMenuType; userNavigationMenu?: UserMenuType; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onLogout?: () => Promise; + onLogout?: () => Promise; } export const UserEnabledSidebarHeaderLayout: React.FC = ({ diff --git a/packages/user/src/layouts/UserEnabledSidebarOnlyLayout.tsx b/packages/user/src/layouts/UserEnabledSidebarOnlyLayout.tsx index bd34d2f40..f03469f7b 100644 --- a/packages/user/src/layouts/UserEnabledSidebarOnlyLayout.tsx +++ b/packages/user/src/layouts/UserEnabledSidebarOnlyLayout.tsx @@ -10,8 +10,7 @@ import type { interface Properties extends Omit { authNavigationMenu?: UserMenuType; userNavigationMenu?: UserMenuType; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onLogout?: () => Promise; + onLogout?: () => Promise; } export const UserEnabledSidebarOnlyLayout: React.FC = ({ diff --git a/packages/user/src/supertokens/change-email.ts b/packages/user/src/supertokens/change-email.ts index 6afe46568..9c9761cc2 100644 --- a/packages/user/src/supertokens/change-email.ts +++ b/packages/user/src/supertokens/change-email.ts @@ -11,10 +11,14 @@ export const changeEmail = async (email: string, apiBaseUrl: string) => { ); return response.data; - /*eslint-disable-next-line @typescript-eslint/no-explicit-any */ - } catch (err: any) { - if (err.response) { - const { data } = err.response; + } catch (error) { + if ( + typeof error === "object" && + error !== null && + "response" in error && + error.response + ) { + const { data } = error.response as { data: Record }; return { status: data.status, message: data.message }; } diff --git a/packages/user/src/supertokens/profile-validation-claim.ts b/packages/user/src/supertokens/profile-validation-claim.ts index 892d53eb1..beb537fdd 100644 --- a/packages/user/src/supertokens/profile-validation-claim.ts +++ b/packages/user/src/supertokens/profile-validation-claim.ts @@ -17,10 +17,11 @@ export class ProfileValidationClaim implements SessionClaim { return undefined; } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - getValueFromPayload(payload: any): Response | undefined { + getValueFromPayload( + payload: Record>, + ): Response | undefined { return payload[ProfileValidationClaim.id] !== undefined - ? payload[ProfileValidationClaim.id].v + ? (payload[ProfileValidationClaim.id]?.v as Response) : undefined; } diff --git a/packages/user/src/supertokens/superTokens.ts b/packages/user/src/supertokens/superTokens.ts index eb3672373..99e2103d5 100644 --- a/packages/user/src/supertokens/superTokens.ts +++ b/packages/user/src/supertokens/superTokens.ts @@ -1,4 +1,6 @@ import SuperTokens from "supertokens-web-js"; +import { PreAndPostAPIHookAction } from "supertokens-web-js/lib/build/recipe/emailpassword/types"; +import { CreateRecipeFunction } from "supertokens-web-js/lib/build/types"; import EmailVerification from "supertokens-web-js/recipe/emailverification"; import Session from "supertokens-web-js/recipe/session"; import ThirdPartyEmailPassword from "supertokens-web-js/recipe/thirdpartyemailpassword"; @@ -7,8 +9,7 @@ import { SUPERTOKENS_API_BASE_PATH_DEFAULT } from "@/constants"; import { UserConfig } from "@/types/config"; export const superTokens = (config: UserConfig) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const recipeLists: Array = [ + const recipeLists: Array = [ Session.init(config?.supertokens?.sessionConfig), ThirdPartyEmailPassword.init( config?.supertokens?.thirdPartyEmailPasswordConfig, @@ -26,6 +27,8 @@ export const superTokens = (config: UserConfig) => { apiBasePath: config.supertokens.apiBasePath || SUPERTOKENS_API_BASE_PATH_DEFAULT, }, - recipeList: recipeLists, + recipeList: recipeLists as Array< + CreateRecipeFunction + >, }); }; diff --git a/packages/user/src/types/invitation.ts b/packages/user/src/types/invitation.ts index aa5b93c8d..26d42e49b 100644 --- a/packages/user/src/types/invitation.ts +++ b/packages/user/src/types/invitation.ts @@ -14,8 +14,7 @@ export interface Invitation { expiresAt: number; id: number; invitedById: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - payload: any; + payload: Record; revokedAt: number | null; role: string; token?: string; @@ -58,5 +57,6 @@ export type RevokeInvitationResponse = Invitation | ErrorResponse; export type GetInvitationResponse = Invitation | ErrorResponse; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type AcceptInvitationResponse = any | ErrorResponse; +export type AcceptInvitationResponse = + | Record> + | ErrorResponse; diff --git a/packages/user/src/views/AcceptInvitation.tsx b/packages/user/src/views/AcceptInvitation.tsx index 0dee26c60..4964db4db 100644 --- a/packages/user/src/views/AcceptInvitation.tsx +++ b/packages/user/src/views/AcceptInvitation.tsx @@ -61,23 +61,21 @@ export const AcceptInvitation = ({ .then((response) => { setAcceptInvitationLoading(false); - if ("data" in response && response.data.status === "ERROR") { + if ("data" in response && response.data?.status === "ERROR") { // TODO better handle errors - toast.error(response.data.message); + toast.error(response.data.message as string); } else { setLoginLoading(true); // TODO acceptInvitation should return authenticated user from api login(credentials) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .then((result: any) => { + .then((result) => { if (result?.user) { setUser(result.user); toast.success(`${t("user:login.messages.success")}`); } }) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .catch((error: any) => { + .catch((error) => { const errorMessage = t("errors:errors.otherErrors"); if (error.name) { diff --git a/packages/user/src/views/SignupFirstUser.tsx b/packages/user/src/views/SignupFirstUser.tsx index f5fc2c2b6..ebcbdcb7a 100644 --- a/packages/user/src/views/SignupFirstUser.tsx +++ b/packages/user/src/views/SignupFirstUser.tsx @@ -56,8 +56,7 @@ export const SignUpFirstUser = ({ // TODO Sign up first-user should return authenticated user from api login(credentials) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .then((result: any) => { + .then((result) => { if (result?.user) { setUser(result.user); toast.success(`${t("login.messages.success")}`); From 3d3804cbf22975ef3d5f36898d617feaed63e2d5 Mon Sep 17 00:00:00 2001 From: shailesh Date: Fri, 6 Mar 2026 17:24:13 +0545 Subject: [PATCH 03/10] chore(layout): replace any --- packages/layout/setup-test.ts | 5 ++--- .../Layout/common/UserMenu/UserMenu.tsx | 22 +++++++++++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/layout/setup-test.ts b/packages/layout/setup-test.ts index dd2bf8773..b0861fe93 100644 --- a/packages/layout/setup-test.ts +++ b/packages/layout/setup-test.ts @@ -2,14 +2,13 @@ import { vi } from "vitest"; // from i18n documentation https://react.i18next.com/misc/testing vi.mock("@prefabs.tech/react-i18n", async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const actual: any = await vi.importActual("@prefabs.tech/react-i18n"); + const actual = await vi.importActual("@prefabs.tech/react-i18n"); return { ...actual, useTranslation: () => { return { - t: (string_) => string_, + t: (string_: string) => string_, i18n: { changeLanguage: () => new Promise(() => {}), }, diff --git a/packages/layout/src/components/Layout/common/UserMenu/UserMenu.tsx b/packages/layout/src/components/Layout/common/UserMenu/UserMenu.tsx index 2ba208de2..fc1eed153 100644 --- a/packages/layout/src/components/Layout/common/UserMenu/UserMenu.tsx +++ b/packages/layout/src/components/Layout/common/UserMenu/UserMenu.tsx @@ -1,4 +1,9 @@ -import { DropdownMenu, NavGroup, NavItem } from "@prefabs.tech/react-ui"; +import { + DropdownMenu, + MenuItem, + NavGroup, + NavItem, +} from "@prefabs.tech/react-ui"; import React, { useMemo } from "react"; import { useNavigate } from "react-router-dom"; @@ -36,11 +41,20 @@ export const UserMenu = ({ menu, userMenuMode, trigger }: IProperties) => { ); const renderContent = () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const template = (_menuItem: any) => { + const template = (_menuItem: MenuItem) => { + const icon = _menuItem.icon ? ( + typeof _menuItem.icon === "string" ? ( + + ) : ( + _menuItem.icon + ) + ) : ( + <> + ); + return ( - {_menuItem.icon && } + {icon} {_menuItem.label} ); From 8078a456942912c9f4bef8135f8d986ffd9edc99 Mon Sep 17 00:00:00 2001 From: shailesh Date: Fri, 6 Mar 2026 17:30:23 +0545 Subject: [PATCH 04/10] fix(demo): type error in invitations table --- packages/user/src/types/invitation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/user/src/types/invitation.ts b/packages/user/src/types/invitation.ts index 26d42e49b..c6be67030 100644 --- a/packages/user/src/types/invitation.ts +++ b/packages/user/src/types/invitation.ts @@ -14,7 +14,7 @@ export interface Invitation { expiresAt: number; id: number; invitedById: string; - payload: Record; + payload: Record | null; revokedAt: number | null; role: string; token?: string; From 1988d97035b8018f056914d43635eb682a12c63e Mon Sep 17 00:00:00 2001 From: shailesh Date: Fri, 6 Mar 2026 18:29:12 +0545 Subject: [PATCH 05/10] chore(form): replace type any --- packages/form/src/components/DateInput.tsx | 6 ++---- packages/form/src/components/Email.tsx | 4 ++-- packages/form/src/components/Form.tsx | 11 ++++------- packages/form/src/components/FormProvider.tsx | 10 ++++------ packages/form/src/components/TextInput.tsx | 4 ++-- packages/form/src/components/Textarea.tsx | 6 ++---- packages/form/src/types/index.ts | 6 ++---- 7 files changed, 18 insertions(+), 29 deletions(-) diff --git a/packages/form/src/components/DateInput.tsx b/packages/form/src/components/DateInput.tsx index f9fc1434a..bc1fd19f1 100644 --- a/packages/form/src/components/DateInput.tsx +++ b/packages/form/src/components/DateInput.tsx @@ -12,10 +12,8 @@ interface IDateInput { showInvalidState?: boolean; showValidState?: boolean; submitCount?: number; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - getFieldState?: UseFormGetFieldState; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - register?: UseFormRegister; + getFieldState?: UseFormGetFieldState>; + register?: UseFormRegister>; } // TODO use Input component from @prefabs.tech/react-ui diff --git a/packages/form/src/components/Email.tsx b/packages/form/src/components/Email.tsx index 406af9f72..1fd5a7c78 100644 --- a/packages/form/src/components/Email.tsx +++ b/packages/form/src/components/Email.tsx @@ -15,9 +15,9 @@ interface IProperties extends IInputProperties { showInvalidState?: boolean; submitCount?: number; /** @deprecated */ - getFieldState?: UseFormGetFieldState; // eslint-disable-line @typescript-eslint/no-explicit-any + getFieldState?: UseFormGetFieldState>; /** @deprecated */ - register?: UseFormRegister; // eslint-disable-line @typescript-eslint/no-explicit-any + register?: UseFormRegister>; } export const Email: React.FC = ({ diff --git a/packages/form/src/components/Form.tsx b/packages/form/src/components/Form.tsx index 52912cbb5..511189636 100644 --- a/packages/form/src/components/Form.tsx +++ b/packages/form/src/components/Form.tsx @@ -1,17 +1,14 @@ import { zodResolver } from "@hookform/resolvers/zod"; import React, { Children, createElement } from "react"; import { UseFormProps, useForm } from "react-hook-form"; -import { ZodEffects, ZodObject } from "zod"; +import { AnyZodObject } from "zod"; interface IForm extends UseFormProps { className?: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - children: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - validationSchema?: ZodObject | ZodEffects; + children: JSX.Element; + validationSchema?: AnyZodObject; html5Validation?: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onSubmit: (data: any) => void; + onSubmit: (data: Record) => void; } export const Form: React.FC = ({ diff --git a/packages/form/src/components/FormProvider.tsx b/packages/form/src/components/FormProvider.tsx index 2f394bb0d..98489d49e 100644 --- a/packages/form/src/components/FormProvider.tsx +++ b/packages/form/src/components/FormProvider.tsx @@ -1,18 +1,17 @@ import { zodResolver } from "@hookform/resolvers/zod"; import React, { useEffect } from "react"; import { UseFormProps, useForm, FormProvider } from "react-hook-form"; -import { ZodEffects, ZodObject } from "zod"; +import { AnyZodObject } from "zod"; import { FormSubmitOptions } from ".."; interface IForm extends UseFormProps { className?: string; children: React.ReactNode; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - validationSchema?: ZodObject | ZodEffects; + validationSchema?: AnyZodObject; html5Validation?: boolean; // eslint-disable-next-line @typescript-eslint/no-explicit-any - onSubmit: (data: any, options?: FormSubmitOptions) => any; + onSubmit: (data: any, options?: FormSubmitOptions) => unknown; validationTriggerKey?: string; } @@ -30,8 +29,7 @@ export const Provider: React.FC = ({ ...useFormOptions, }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handleOnSubmit = async (data: any) => { + const handleOnSubmit = async (data: Record) => { try { const formSubmitOptions = { clearErrors: methods.clearErrors, diff --git a/packages/form/src/components/TextInput.tsx b/packages/form/src/components/TextInput.tsx index 0c8b0ec6e..6e83e2374 100644 --- a/packages/form/src/components/TextInput.tsx +++ b/packages/form/src/components/TextInput.tsx @@ -16,9 +16,9 @@ interface ITextInput extends IInputProperties { showInvalidState?: boolean; submitCount?: number; /** @deprecated */ - getFieldState?: UseFormGetFieldState; // eslint-disable-line @typescript-eslint/no-explicit-any + getFieldState?: UseFormGetFieldState>; /** @deprecated */ - register?: UseFormRegister; // eslint-disable-line @typescript-eslint/no-explicit-any + register?: UseFormRegister>; } export const TextInput: React.FC = ({ diff --git a/packages/form/src/components/Textarea.tsx b/packages/form/src/components/Textarea.tsx index 825629884..aa60d8f20 100644 --- a/packages/form/src/components/Textarea.tsx +++ b/packages/form/src/components/Textarea.tsx @@ -18,11 +18,9 @@ interface ITextarea extends ITextareaProperties { showInvalidState?: boolean; submitCount?: number; /** @deprecated */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - getFieldState?: UseFormGetFieldState; + getFieldState?: UseFormGetFieldState>; /** @deprecated */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - register?: UseFormRegister; + register?: UseFormRegister>; } export const Textarea: React.FC = ({ diff --git a/packages/form/src/types/index.ts b/packages/form/src/types/index.ts index 4487ac0bc..e3d7bd2fb 100644 --- a/packages/form/src/types/index.ts +++ b/packages/form/src/types/index.ts @@ -21,14 +21,12 @@ interface PasswordErrorMessages { interface CustomInputProperties { disabled?: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - getFieldState?: UseFormGetFieldState; + getFieldState?: UseFormGetFieldState>; helperText?: string; label?: string | React.ReactNode; name: string; placeholder?: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - register?: UseFormRegister; + register?: UseFormRegister>; showValidState?: boolean; showInvalidState?: boolean; submitCount?: number; From e83867f7c0077429d595354599ead5bd51e59c8d Mon Sep 17 00:00:00 2001 From: shailesh Date: Mon, 9 Mar 2026 22:36:22 +0545 Subject: [PATCH 06/10] fix(ui): replace type any --- .../ui/src/Buttons/ExportButton/index.tsx | 3 +-- packages/ui/src/FileCard/index.tsx | 6 ++++-- packages/ui/src/FilesTable/index.tsx | 3 +-- packages/ui/src/FormWidgets/Select/index.tsx | 2 +- packages/ui/src/SortableList/SortableList.tsx | 13 ++++++------ packages/ui/src/Table/Table.tsx | 3 +-- packages/ui/src/Table/TableBody.tsx | 21 +++++++------------ packages/ui/src/Table/TableHeader.tsx | 5 ++--- packages/ui/src/Table/TableToolbar.tsx | 4 +++- packages/ui/src/Table/types.ts | 3 +-- packages/ui/src/utils/UseExporter.ts | 9 +++----- packages/ui/src/utils/UseExporterAsync.ts | 9 +++----- .../Invitation/InvitationsTable.tsx | 10 ++++----- 13 files changed, 39 insertions(+), 52 deletions(-) diff --git a/packages/ui/src/Buttons/ExportButton/index.tsx b/packages/ui/src/Buttons/ExportButton/index.tsx index 7afc26bc8..dcf722b4e 100644 --- a/packages/ui/src/Buttons/ExportButton/index.tsx +++ b/packages/ui/src/Buttons/ExportButton/index.tsx @@ -11,8 +11,7 @@ export interface ExportButtonProperties extends ComponentProps { sheetOptions?: WorkSheetOptions; onExportStart?: () => void; onExportEnd?: () => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - getData: () => Array>; + getData: () => Array>; } export const ExportButton: React.FC = ({ diff --git a/packages/ui/src/FileCard/index.tsx b/packages/ui/src/FileCard/index.tsx index 7329818c5..3bcceab1e 100644 --- a/packages/ui/src/FileCard/index.tsx +++ b/packages/ui/src/FileCard/index.tsx @@ -109,8 +109,10 @@ export const FileCard = ({ ); }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const checkUploadedByData = (data: any) => { + + const checkUploadedByData = (data: { + uploadedBy: Record; + }) => { if (!data.uploadedBy) { return ; } diff --git a/packages/ui/src/FilesTable/index.tsx b/packages/ui/src/FilesTable/index.tsx index f36f98f83..c2c5c4bac 100644 --- a/packages/ui/src/FilesTable/index.tsx +++ b/packages/ui/src/FilesTable/index.tsx @@ -22,8 +22,7 @@ export interface IFile { originalFileName: string; description?: string; size?: number; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - uploadedBy: any; + uploadedBy: Record; uploadedAt: number; downloadCount?: number; lastDownloadedAt?: number; diff --git a/packages/ui/src/FormWidgets/Select/index.tsx b/packages/ui/src/FormWidgets/Select/index.tsx index eff8869c6..c203e4504 100644 --- a/packages/ui/src/FormWidgets/Select/index.tsx +++ b/packages/ui/src/FormWidgets/Select/index.tsx @@ -374,7 +374,7 @@ export const Select = ({ if (multiple) { onChange([]); } else { - onChange(null as any); // eslint-disable-line @typescript-eslint/no-explicit-any + onChange(null as unknown as T); } setSearchInput(""); diff --git a/packages/ui/src/SortableList/SortableList.tsx b/packages/ui/src/SortableList/SortableList.tsx index d7a002888..aba64d115 100644 --- a/packages/ui/src/SortableList/SortableList.tsx +++ b/packages/ui/src/SortableList/SortableList.tsx @@ -5,13 +5,10 @@ import type { FC, ReactNode } from "react"; export interface SortableListProperties { items: { id: number; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - data: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - render?: (data: any) => ReactNode; + data: unknown; + render?: (data: unknown) => ReactNode; }[]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onSort?: (sortedItems: { id: number; data: any }[]) => void; + onSort?: (sortedItems: { id: number; data: unknown }[]) => void; itemClassName?: string; className?: string; grabHandleIcon?: ReactNode; @@ -87,7 +84,9 @@ export const SortableList: FC = ({ )} -
{item.render ? item.render(item.data) : item.data}
+
+ {item.render ? item.render(item.data) : (item.data as ReactNode)} +
))} diff --git a/packages/ui/src/Table/Table.tsx b/packages/ui/src/Table/Table.tsx index 2ea350ccf..e45d81b19 100644 --- a/packages/ui/src/Table/Table.tsx +++ b/packages/ui/src/Table/Table.tsx @@ -317,8 +317,7 @@ const DataTable = ({ if (!filterValue || filterValue.length === 0) { return row; } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return filterValue.some((value: any) => + return filterValue.some((value: unknown) => row.getValue(columnId)?.includes(value), ); }; diff --git a/packages/ui/src/Table/TableBody.tsx b/packages/ui/src/Table/TableBody.tsx index bf6662321..55d83b238 100644 --- a/packages/ui/src/Table/TableBody.tsx +++ b/packages/ui/src/Table/TableBody.tsx @@ -73,7 +73,7 @@ export const TableBody = ({ table.getRowModel().rows.map((row) => ( ({ const getFormattedValue = (): NoInfer => { const defaultCustomFormatters: Record< string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (value: any) => NoInfer + (value: unknown) => NoInfer > = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - number: (value: any) => + number: (value: unknown) => formatNumber({ value: Number(value), locale: numberOptions?.locale ?? locale, formatOptions: numberOptions?.formatOptions, }) as NoInfer, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - date: (value: any) => + date: (value: unknown) => formatDate( - value, + value as string, dateOptions?.locale ?? locale, dateOptions?.formatOptions ?? defaultDateOptions, ) as NoInfer, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - datetime: (value: any) => + datetime: (value: unknown) => formatDateTime( - value, + value as string, dateOptions?.locale ?? locale, dateOptions?.formatOptions ?? defaultDateTimeOptions, ) as NoInfer, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - currency: (value: any) => + currency: (value: unknown) => formatNumber({ value: Number(value), locale: numberOptions?.locale ?? locale, diff --git a/packages/ui/src/Table/TableHeader.tsx b/packages/ui/src/Table/TableHeader.tsx index 7656a8e3a..6359082bc 100644 --- a/packages/ui/src/Table/TableHeader.tsx +++ b/packages/ui/src/Table/TableHeader.tsx @@ -1,4 +1,4 @@ -import { flexRender, RowData, Table } from "@tanstack/react-table"; +import { Column, flexRender, RowData, Table } from "@tanstack/react-table"; import React, { SyntheticEvent, useCallback, useState } from "react"; import { DebouncedInput, Select } from "@/FormWidgets"; @@ -118,8 +118,7 @@ export const TableHeader = ({ )); - //eslint-disable-next-line @typescript-eslint/no-explicit-any - const renderColumnFilter = (column: any) => { + const renderColumnFilter = (column: Column) => { if (column.columnDef.customFilterComponent) { return column.columnDef.customFilterComponent(column); } diff --git a/packages/ui/src/Table/TableToolbar.tsx b/packages/ui/src/Table/TableToolbar.tsx index 0f81c3f08..59780e963 100644 --- a/packages/ui/src/Table/TableToolbar.tsx +++ b/packages/ui/src/Table/TableToolbar.tsx @@ -84,7 +84,9 @@ export const TableToolbar = ({ onSort={(sorted) => { table.setColumnOrder([ ...(enableRowSelection ? ["select"] : []), - ...sorted.map((item) => item.data.id), + ...sorted.map( + (item) => (item.data as { id: string })?.id, + ), ...(dataActionsMenu ? ["actions"] : []), ]); }} diff --git a/packages/ui/src/Table/types.ts b/packages/ui/src/Table/types.ts index 53fc18f3a..d7e97ff87 100644 --- a/packages/ui/src/Table/types.ts +++ b/packages/ui/src/Table/types.ts @@ -214,8 +214,7 @@ export interface TDataTableProperties extends Partial< > { className?: string; columnActionBtnLabel?: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - customFormatters?: Record string>; + customFormatters?: Record string>; dataActionsMenu?: | ((data: TData) => DataActionsMenuProperties) | DataActionsMenuProperties; diff --git a/packages/ui/src/utils/UseExporter.ts b/packages/ui/src/utils/UseExporter.ts index e534f3122..c8b8eea56 100644 --- a/packages/ui/src/utils/UseExporter.ts +++ b/packages/ui/src/utils/UseExporter.ts @@ -10,8 +10,7 @@ type UseExporterOptions = { onExportEnd?: () => void; }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type TriggerExportType = (data: any) => void; +type TriggerExportType = (data: unknown[][]) => void; const exportXLSX = ({ sheetName, @@ -21,8 +20,7 @@ const exportXLSX = ({ }: { sheetName: string; filename: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - data: any; + data: unknown[][]; sheetOptions: WorkSheetOptions; }) => { const buffer = build([{ name: sheetName, data, options: sheetOptions }]); @@ -45,8 +43,7 @@ export const useExporter = ({ const [exporting, setExporting] = useState(false); const triggerExport = useCallback( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (data: any) => { + (data: unknown[][]) => { setExporting(true); if (onExportStart) { onExportStart(); diff --git a/packages/ui/src/utils/UseExporterAsync.ts b/packages/ui/src/utils/UseExporterAsync.ts index 95bc46997..4fea445ee 100644 --- a/packages/ui/src/utils/UseExporterAsync.ts +++ b/packages/ui/src/utils/UseExporterAsync.ts @@ -10,8 +10,7 @@ type UseExporterOptions = { onExportEnd?: () => void; }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type TriggerExportAsyncType = (data: any) => Promise; +type TriggerExportAsyncType = (data: unknown[][]) => Promise; const exportXLSX = async ({ sheetName, @@ -21,8 +20,7 @@ const exportXLSX = async ({ }: { sheetName: string; filename: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - data: any; + data: unknown[][]; sheetOptions: WorkSheetOptions; }) => { const XLSX = await import("node-xlsx"); @@ -47,8 +45,7 @@ export const useExporterAsync = ({ const [exporting, setExporting] = useState(false); const triggerExportAsync = useCallback( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - async (data: any) => { + async (data: unknown[][]) => { setExporting(true); if (onExportStart) { onExportStart(); diff --git a/packages/user/src/components/Invitation/InvitationsTable.tsx b/packages/user/src/components/Invitation/InvitationsTable.tsx index c4e8e1408..bd586cdf8 100644 --- a/packages/user/src/components/Invitation/InvitationsTable.tsx +++ b/packages/user/src/components/Invitation/InvitationsTable.tsx @@ -354,11 +354,11 @@ export const InvitationsTable = ({ { label: t("invitations.actions.resend"), icon: "pi pi-replay", - disabled: (invitation) => + disabled: (invitation: Invitation) => !!invitation.acceptedAt || !!invitation.revokedAt || isExpired(invitation.expiresAt), - onClick: (invitation) => handleResendInvitation(invitation), + onClick: handleResendInvitation, requireConfirmationModal: true, confirmationOptions: { message: t("confirmation.confirm.resend.message"), @@ -369,11 +369,11 @@ export const InvitationsTable = ({ label: t("invitations.actions.revoke"), icon: "pi pi-times", className: "danger", - disabled: (invitation) => + disabled: (invitation: Invitation) => !!invitation.acceptedAt || !!invitation.revokedAt || isExpired(invitation.expiresAt), - onClick: (invitation) => handleRevokeInvitation(invitation), + onClick: handleRevokeInvitation, requireConfirmationModal: true, confirmationOptions: { message: t("confirmation.confirm.revoke.message"), @@ -384,7 +384,7 @@ export const InvitationsTable = ({ label: t("invitations.actions.delete"), icon: "pi pi-trash", className: "danger", - onClick: (invitation) => handleDeleteInvitation(invitation.id), + onClick: handleDeleteInvitation, requireConfirmationModal: true, confirmationOptions: { message: t("confirmation.confirm.delete.message"), From 257ed2c8d1bbac5aa4673ad014925719d6453369 Mon Sep 17 00:00:00 2001 From: shailesh Date: Tue, 10 Mar 2026 16:00:56 +0545 Subject: [PATCH 07/10] chore(demo): replace any with proper type --- .../FileInput/_components/FormFileInputButton.tsx | 3 +-- .../FileInput/_components/FormWithFileInput.tsx | 3 +-- .../src/Views/Form/components/FormInput/FormInput.tsx | 3 +-- .../Views/Form/components/FormInput/FormInputFields.tsx | 9 +++------ apps/demo/src/Views/Ui/components/DropdownMenuDemo.tsx | 9 ++++++--- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/apps/demo/src/Views/Form/components/FileInput/_components/FormFileInputButton.tsx b/apps/demo/src/Views/Form/components/FileInput/_components/FormFileInputButton.tsx index 16cda4d75..8b4e21fda 100644 --- a/apps/demo/src/Views/Form/components/FileInput/_components/FormFileInputButton.tsx +++ b/apps/demo/src/Views/Form/components/FileInput/_components/FormFileInputButton.tsx @@ -8,8 +8,7 @@ import { UploadBy } from "./FormWithFileInput"; export const FormWithFileInputButton: React.FC = () => { const { t } = useTranslation("files"); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const onSubmit = (values: any) => { + const onSubmit = (values: Record) => { const formData = new FormData(); for (const name in values) { diff --git a/apps/demo/src/Views/Form/components/FileInput/_components/FormWithFileInput.tsx b/apps/demo/src/Views/Form/components/FileInput/_components/FormWithFileInput.tsx index 87390caf7..82703cd21 100644 --- a/apps/demo/src/Views/Form/components/FileInput/_components/FormWithFileInput.tsx +++ b/apps/demo/src/Views/Form/components/FileInput/_components/FormWithFileInput.tsx @@ -11,8 +11,7 @@ import React from "react"; export const FormWithFileInput: React.FC = () => { const { t } = useTranslation("files"); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const onSubmit = (values: any) => { + const onSubmit = (values: Record) => { const formData = new FormData(); for (const name in values) { diff --git a/apps/demo/src/Views/Form/components/FormInput/FormInput.tsx b/apps/demo/src/Views/Form/components/FormInput/FormInput.tsx index 725225529..e7f383f4c 100644 --- a/apps/demo/src/Views/Form/components/FormInput/FormInput.tsx +++ b/apps/demo/src/Views/Form/components/FormInput/FormInput.tsx @@ -59,8 +59,7 @@ export const FormInputDemo = () => { }), }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handleSubmit = (_formData: any) => { + const handleSubmit = (_formData: Record) => { setFormData(JSON.stringify(_formData, null, 4)); }; diff --git a/apps/demo/src/Views/Form/components/FormInput/FormInputFields.tsx b/apps/demo/src/Views/Form/components/FormInput/FormInputFields.tsx index bdc3274cd..f7dff96b9 100644 --- a/apps/demo/src/Views/Form/components/FormInput/FormInputFields.tsx +++ b/apps/demo/src/Views/Form/components/FormInput/FormInputFields.tsx @@ -25,8 +25,7 @@ type Properties = { export const FormInputFields = ({ checkFilledState }: Properties) => { const [t] = useTranslation("form"); const [isLoading, setIsLoading] = useState(false); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const [options, setOptions] = useState([]); + const [options, setOptions] = useState[]>([]); const { register, getFieldState, @@ -36,15 +35,13 @@ export const FormInputFields = ({ checkFilledState }: Properties) => { const [filled, valid, invalid] = watch(["filled", "valid", "invalid"]); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handleDataFetch = (value: any) => { + const handleDataFetch = (value: string | number | readonly string[]) => { setIsLoading(true); fetch(`https://api.escuelajs.co/api/v1/products/?title=${value}`) .then(async (response) => { const data = await response.json(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - setOptions(data.map((item: any) => item)); + setOptions(data.map((item: unknown) => item)); setIsLoading(false); }) .catch((err) => console.log("err", err)); // eslint-disable-line no-console diff --git a/apps/demo/src/Views/Ui/components/DropdownMenuDemo.tsx b/apps/demo/src/Views/Ui/components/DropdownMenuDemo.tsx index 412f76b93..2178a93a0 100644 --- a/apps/demo/src/Views/Ui/components/DropdownMenuDemo.tsx +++ b/apps/demo/src/Views/Ui/components/DropdownMenuDemo.tsx @@ -42,11 +42,14 @@ export const DropdownMenuDemo = () => { }, ]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const template = (item: any) => { + const template = (item: MenuItem) => { return ( <> - + {typeof item.icon === "string" ? ( + + ) : ( + item.icon + )} {item.label} ); From 863b9c4edeed4e1db95180999f7e2d9eb9043e23 Mon Sep 17 00:00:00 2001 From: shailesh Date: Tue, 10 Mar 2026 17:32:43 +0545 Subject: [PATCH 08/10] chore(demo): replace any type --- .../Ui/components/FormWidgets/Typeahead.tsx | 28 +++++++++---------- .../Views/Ui/components/Stepper/Stepper.tsx | 13 ++++++--- .../Views/Ui/components/TabView/utilities.ts | 10 +++---- .../src/Views/Ui/components/Table/Table.tsx | 9 ++---- packages/ui/src/index.ts | 9 +++++- 5 files changed, 37 insertions(+), 32 deletions(-) diff --git a/apps/demo/src/Views/Ui/components/FormWidgets/Typeahead.tsx b/apps/demo/src/Views/Ui/components/FormWidgets/Typeahead.tsx index 1c9ef7b41..c831e9bee 100644 --- a/apps/demo/src/Views/Ui/components/FormWidgets/Typeahead.tsx +++ b/apps/demo/src/Views/Ui/components/FormWidgets/Typeahead.tsx @@ -53,50 +53,48 @@ export const TypeaheadDemo = () => { const [isLoading, setIsLoading] = useState(false); const [options, setOptions] = useState([]); - const [suggestions, setSuggestions] = useState([]); + const [suggestions, setSuggestions] = useState([]); const [customSuggestions, setCustomSuggestions] = useState< Array >([]); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handleDataFetch = (value: any) => { + const handleDataFetch = (value: string | number | readonly string[]) => { setIsLoading(true); fetch(`https://api.escuelajs.co/api/v1/products/?title=${value}`) .then(async (response) => { const data = await response.json(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - setOptions(data.map((item: any) => item.title)); + setOptions(data.map((item: Record) => item.title)); setIsLoading(false); }) .catch((err) => console.log("err", err)); // eslint-disable-line no-console }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handleServerChange = (value: any) => { + const handleServerChange = (value: unknown) => { console.log("selected server value:", value); // eslint-disable-line no-console }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handleDataFilter = (value: any) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let newSuggestions: any = []; + const handleDataFilter = (value: string | number | readonly string[]) => { + let newSuggestions = []; - if (value.length > 0) { + if (typeof value === "string" && value.length) { newSuggestions = items.filter((_value) => _value.toLowerCase().startsWith(value.toLowerCase()), ); + setSuggestions(newSuggestions); } }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handleCustomSuggestionDataFilter = (value: any) => { + const handleCustomSuggestionDataFilter = ( + value: string | number | readonly string[], + ) => { let newSuggestions = []; - if (value && value.length) { + if (typeof value === "string" && value.length) { newSuggestions = suggestionItems.filter((_value) => _value.value.toLowerCase().includes(value.toLowerCase()), ); + setCustomSuggestions(newSuggestions); } }; diff --git a/apps/demo/src/Views/Ui/components/Stepper/Stepper.tsx b/apps/demo/src/Views/Ui/components/Stepper/Stepper.tsx index d4b4b7b9b..04f2a17bb 100644 --- a/apps/demo/src/Views/Ui/components/Stepper/Stepper.tsx +++ b/apps/demo/src/Views/Ui/components/Stepper/Stepper.tsx @@ -1,5 +1,11 @@ import { useTranslation } from "@prefabs.tech/react-i18n"; -import { Button, Divider, Stepper, Page } from "@prefabs.tech/react-ui"; +import { + Button, + Divider, + Stepper, + Page, + IStepEvent, +} from "@prefabs.tech/react-ui"; import { useState } from "react"; import { useNavigate } from "react-router-dom"; @@ -127,9 +133,8 @@ export const StepperDemo = () => { hideButtons={true} activeIndex={activeIndex} readOnly={true} - // eslint-disable-next-line @typescript-eslint/no-explicit-any - onChange={(event: any) => { - setActiveIndex(event.index); + onChange={(event: IStepEvent) => { + event.index && setActiveIndex(event.index); }} align="start" /> diff --git a/apps/demo/src/Views/Ui/components/TabView/utilities.ts b/apps/demo/src/Views/Ui/components/TabView/utilities.ts index 0f9d1eded..f317c1656 100644 --- a/apps/demo/src/Views/Ui/components/TabView/utilities.ts +++ b/apps/demo/src/Views/Ui/components/TabView/utilities.ts @@ -1,13 +1,11 @@ export const addTab = ( key: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - visibleTabs: any[], - // eslint-disable-next-line @typescript-eslint/no-explicit-any - setVisibleTabs: any, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - setActive: any, + visibleTabs: string[], + setVisibleTabs: (value: string[]) => void, + setActive: (value: string) => void, ) => { const existingTab = visibleTabs.find((tab) => tab === key); + if (existingTab) { setActive(existingTab); } else { diff --git a/apps/demo/src/Views/Ui/components/Table/Table.tsx b/apps/demo/src/Views/Ui/components/Table/Table.tsx index 02d53af17..3683cb7a6 100644 --- a/apps/demo/src/Views/Ui/components/Table/Table.tsx +++ b/apps/demo/src/Views/Ui/components/Table/Table.tsx @@ -80,8 +80,7 @@ export const TableDemo = () => { }, ]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const inDateRangeFilter: FilterFunction = ( + const inDateRangeFilter: FilterFunction = ( row, columnId, value: [Date, Date], @@ -104,8 +103,7 @@ export const TableDemo = () => { ); }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const customEqualStringFilter: FilterFunction = ( + const customEqualStringFilter: FilterFunction = ( row, columnId, value: string, @@ -1267,8 +1265,7 @@ export const TableDemo = () => { return true; } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const updatedFilterValue = filterValue.map((value: any) => { + const updatedFilterValue = filterValue.map((value: unknown) => { switch (value) { case "true": return true; diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index a9cf9843a..d97f30064 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -15,6 +15,7 @@ import Modal from "./Modal"; import Page, { PageProperties } from "./Page"; import { FacebookButton, GoogleButton } from "./SSOButtons"; import { Stepper } from "./Stepper"; +import { IStepEvent } from "./Stepper/Step"; import { TabbedPanel } from "./TabbedPanel"; import TabView from "./TabView"; @@ -60,4 +61,10 @@ export { ConfirmationModal, }; -export type { DropdownMenuProperties, MenuItem, PageProperties, Tab }; +export type { + DropdownMenuProperties, + IStepEvent, + MenuItem, + PageProperties, + Tab, +}; From f843033b97c620d1127ac9da83dda73aeb824caa Mon Sep 17 00:00:00 2001 From: shailesh Date: Wed, 11 Mar 2026 15:12:10 +0545 Subject: [PATCH 09/10] fix(ui): safe parse date value --- packages/ui/src/Table/TableBody.tsx | 154 ++++++++++++++-------------- 1 file changed, 78 insertions(+), 76 deletions(-) diff --git a/packages/ui/src/Table/TableBody.tsx b/packages/ui/src/Table/TableBody.tsx index 55d83b238..58dc06cc1 100644 --- a/packages/ui/src/Table/TableBody.tsx +++ b/packages/ui/src/Table/TableBody.tsx @@ -5,6 +5,7 @@ import { NoInfer, Row, RowData, + CellContext, } from "@tanstack/react-table"; import React from "react"; @@ -65,6 +66,81 @@ export const TableBody = ({ return rowClassName({ row }); }; + const getFormattedValueContext = ( + cell: Cell, + ): CellContext => { + const cellContext = cell.getContext(); + const renderValue = cellContext.getValue; + + const dateOptions = cell.column.columnDef.dateOptions; + const defaultDateOptions: Intl.DateTimeFormatOptions = { + day: "2-digit", + month: "2-digit", + year: "numeric", + }; + const defaultDateTimeOptions: Intl.DateTimeFormatOptions = { + ...defaultDateOptions, + hour: "2-digit", + minute: "2-digit", + hour12: false, + }; + + const numberOptions = cell.column.columnDef.numberOptions; + + const getFormattedValue = (): NoInfer => { + const defaultCustomFormatters: Record< + string, + (value: unknown) => NoInfer + > = { + number: (value: unknown) => + formatNumber({ + value: Number(value), + locale: numberOptions?.locale ?? locale, + formatOptions: numberOptions?.formatOptions, + }) as NoInfer, + date: (value: unknown) => + (typeof value === "string" || typeof value === "number" + ? formatDate( + value, + dateOptions?.locale ?? locale, + dateOptions?.formatOptions ?? defaultDateOptions, + ) + : null) as NoInfer, + datetime: (value: unknown) => + (typeof value === "string" || typeof value === "number" + ? formatDateTime( + value, + dateOptions?.locale ?? locale, + dateOptions?.formatOptions ?? defaultDateTimeOptions, + ) + : null) as NoInfer, + currency: (value: unknown) => + formatNumber({ + value: Number(value), + locale: numberOptions?.locale ?? locale, + formatOptions: { + style: "currency", + currency: "USD", + ...(numberOptions?.formatOptions && numberOptions.formatOptions), + }, + }) as NoInfer, + ...customFormatters, + }; + + const dataType: string = cell.column.columnDef.dataType || "text"; + + return ( + defaultCustomFormatters?.[dataType]?.(renderValue()) || renderValue() + ); + }; + + return { + ...cellContext, + renderValue: () => getFormattedValue(), + getValue: () => getFormattedValue(), + }; + }; + return ( {isLoading ? null : ( @@ -80,80 +156,6 @@ export const TableBody = ({ })} > {row.getVisibleCells().map((cell) => { - const getFormattedValueContext: typeof cell.getContext = - () => { - const cellContext = cell.getContext(); - const renderValue = cellContext.getValue; - const dateOptions = cell.column.columnDef.dateOptions; - const defaultDateOptions: Intl.DateTimeFormatOptions = { - day: "2-digit", - month: "2-digit", - year: "numeric", - }; - const defaultDateTimeOptions: Intl.DateTimeFormatOptions = - { - ...defaultDateOptions, - hour: "2-digit", - minute: "2-digit", - hour12: false, - }; - const numberOptions = cell.column.columnDef.numberOptions; - - const getFormattedValue = (): NoInfer => { - const defaultCustomFormatters: Record< - string, - (value: unknown) => NoInfer - > = { - number: (value: unknown) => - formatNumber({ - value: Number(value), - locale: numberOptions?.locale ?? locale, - formatOptions: numberOptions?.formatOptions, - }) as NoInfer, - date: (value: unknown) => - formatDate( - value as string, - dateOptions?.locale ?? locale, - dateOptions?.formatOptions ?? defaultDateOptions, - ) as NoInfer, - datetime: (value: unknown) => - formatDateTime( - value as string, - dateOptions?.locale ?? locale, - dateOptions?.formatOptions ?? - defaultDateTimeOptions, - ) as NoInfer, - currency: (value: unknown) => - formatNumber({ - value: Number(value), - locale: numberOptions?.locale ?? locale, - formatOptions: { - style: "currency", - currency: "USD", - ...(numberOptions?.formatOptions && - numberOptions.formatOptions), - }, - }) as NoInfer, - ...customFormatters, - }; - - const dataType: string = - cell.column.columnDef.dataType || "text"; - - return ( - defaultCustomFormatters?.[dataType]?.( - renderValue(), - ) || renderValue() - ); - }; - - return { - ...cellContext, - renderValue: () => getFormattedValue(), - getValue: () => getFormattedValue(), - }; - }; - return ( ({ }} cellContent={flexRender( cell.column.columnDef.cell, - getFormattedValueContext(), + getFormattedValueContext(cell), )} > ) : ( flexRender( cell.column.columnDef.cell, - getFormattedValueContext(), + getFormattedValueContext(cell), ) )} From 3a8ebc65d3cc1248e58f05b0f8fcc86c8d3d360c Mon Sep 17 00:00:00 2001 From: shailesh Date: Wed, 11 Mar 2026 15:47:15 +0545 Subject: [PATCH 10/10] fix: replace unknow with known type --- .../Views/Form/components/FormInput/FormInputFields.tsx | 4 +++- .../demo/src/Views/Ui/components/FormWidgets/Typeahead.tsx | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/demo/src/Views/Form/components/FormInput/FormInputFields.tsx b/apps/demo/src/Views/Form/components/FormInput/FormInputFields.tsx index f7dff96b9..901cd47e8 100644 --- a/apps/demo/src/Views/Form/components/FormInput/FormInputFields.tsx +++ b/apps/demo/src/Views/Form/components/FormInput/FormInputFields.tsx @@ -25,7 +25,9 @@ type Properties = { export const FormInputFields = ({ checkFilledState }: Properties) => { const [t] = useTranslation("form"); const [isLoading, setIsLoading] = useState(false); - const [options, setOptions] = useState[]>([]); + const [options, setOptions] = useState< + { title: string; [key: string]: unknown }[] + >([]); const { register, getFieldState, diff --git a/apps/demo/src/Views/Ui/components/FormWidgets/Typeahead.tsx b/apps/demo/src/Views/Ui/components/FormWidgets/Typeahead.tsx index c831e9bee..450c58fe2 100644 --- a/apps/demo/src/Views/Ui/components/FormWidgets/Typeahead.tsx +++ b/apps/demo/src/Views/Ui/components/FormWidgets/Typeahead.tsx @@ -52,7 +52,7 @@ export const TypeaheadDemo = () => { const navigate = useNavigate(); const [isLoading, setIsLoading] = useState(false); - const [options, setOptions] = useState([]); + const [options, setOptions] = useState([]); const [suggestions, setSuggestions] = useState([]); const [customSuggestions, setCustomSuggestions] = useState< Array @@ -63,13 +63,14 @@ export const TypeaheadDemo = () => { fetch(`https://api.escuelajs.co/api/v1/products/?title=${value}`) .then(async (response) => { const data = await response.json(); - setOptions(data.map((item: Record) => item.title)); + + setOptions(data.map((item: { title: string }) => item.title)); setIsLoading(false); }) .catch((err) => console.log("err", err)); // eslint-disable-line no-console }; - const handleServerChange = (value: unknown) => { + const handleServerChange = (value?: string) => { console.log("selected server value:", value); // eslint-disable-line no-console };