diff --git a/examples/checkout/shipments.tsx b/examples/checkout/shipments.tsx index 98213c4d..fecebe81 100644 --- a/examples/checkout/shipments.tsx +++ b/examples/checkout/shipments.tsx @@ -22,7 +22,7 @@ import { ShippingMethodRadioButtonType, Errors, } from 'packages/react-components/src' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from 'packages/react-components/src/utils/isEmpty' import { useRouter } from 'next/router' import getSdk from '#utils/getSdk' diff --git a/packages/react-components/package.json b/packages/react-components/package.json index 9d126e66..37b86dee 100644 --- a/packages/react-components/package.json +++ b/packages/react-components/package.json @@ -68,7 +68,6 @@ "frames-react": "^1.2.3", "iframe-resizer": "^4.3.6", "jwt-decode": "^4.0.0", - "lodash": "^4.17.21", "rapid-form": "3.1.0" }, "devDependencies": { @@ -79,7 +78,6 @@ "@testing-library/dom": "^10.4.1", "@testing-library/react": "^16.3.1", "@types/braintree-web": "^3.96.17", - "@types/lodash": "^4.17.21", "@types/node": "^25.0.3", "@types/prop-types": "^15.7.15", "@types/react": "^19.1.8", diff --git a/packages/react-components/src/components/SubmitButton.tsx b/packages/react-components/src/components/SubmitButton.tsx index f5092cd2..35072a90 100644 --- a/packages/react-components/src/components/SubmitButton.tsx +++ b/packages/react-components/src/components/SubmitButton.tsx @@ -1,13 +1,12 @@ import type { ReactNode, JSX } from 'react'; import Parent from '#components/utils/Parent' import type { ChildrenFunction } from '#typings/index' -import isFunction from 'lodash/isFunction' interface ChildrenProps extends Omit {} interface Props extends Omit { children?: ChildrenFunction - label?: string | ReactNode + label?: string | ReactNode | (() => ReactNode) } export function SubmitButton(props: Props): JSX.Element { @@ -20,7 +19,7 @@ export function SubmitButton(props: Props): JSX.Element { {children} ) : ( ) } diff --git a/packages/react-components/src/components/addresses/Address.tsx b/packages/react-components/src/components/addresses/Address.tsx index 05de5c56..4f2d5351 100644 --- a/packages/react-components/src/components/addresses/Address.tsx +++ b/packages/react-components/src/components/addresses/Address.tsx @@ -1,5 +1,5 @@ import type { Address as AddressType } from "@commercelayer/sdk" -import isEmpty from "lodash/isEmpty" +import { isEmpty } from "#utils/isEmpty" import { type JSX, useContext, useEffect, useState } from "react" import AddressCardsTemplate, { type AddressCardsTemplateChildren, diff --git a/packages/react-components/src/components/addresses/AddressStateSelector.tsx b/packages/react-components/src/components/addresses/AddressStateSelector.tsx index 7bf3612c..71e44ccd 100644 --- a/packages/react-components/src/components/addresses/AddressStateSelector.tsx +++ b/packages/react-components/src/components/addresses/AddressStateSelector.tsx @@ -7,7 +7,7 @@ import type { } from "#typings" import BillingAddressFormContext from "#context/BillingAddressFormContext" import ShippingAddressFormContext from "#context/ShippingAddressFormContext" -import isEmpty from "lodash/isEmpty" +import { isEmpty } from "#utils/isEmpty" import { getStateOfCountry, isValidState, diff --git a/packages/react-components/src/components/addresses/SaveAddressesButton.tsx b/packages/react-components/src/components/addresses/SaveAddressesButton.tsx index 4a5fcbe3..6e5da80c 100644 --- a/packages/react-components/src/components/addresses/SaveAddressesButton.tsx +++ b/packages/react-components/src/components/addresses/SaveAddressesButton.tsx @@ -1,5 +1,4 @@ import type { Order } from "@commercelayer/sdk" -import isFunction from "lodash/isFunction" import { type JSX, type ReactNode, useContext, useState } from "react" import Parent from "#components/utils/Parent" import AddressContext from "#context/AddressContext" @@ -24,7 +23,7 @@ interface ChildrenProps extends Omit {} interface Props extends Omit { children?: ChildrenFunction - label?: string | ReactNode + label?: string | ReactNode | (() => ReactNode) onClick?: (params: TOnClick) => void addressId?: string requiredMetadataFields?: string[] @@ -179,7 +178,7 @@ export function SaveAddressesButton(props: Props): JSX.Element { }} {...p} > - {isFunction(label) ? label() : label} + {typeof label === 'function' ? label() : label} ) } diff --git a/packages/react-components/src/components/customers/SaveCustomerButton.tsx b/packages/react-components/src/components/customers/SaveCustomerButton.tsx index a47d68a8..d4a1ecce 100644 --- a/packages/react-components/src/components/customers/SaveCustomerButton.tsx +++ b/packages/react-components/src/components/customers/SaveCustomerButton.tsx @@ -1,7 +1,7 @@ import { type ReactNode, useContext, type JSX } from 'react'; import Parent from '#components/utils/Parent' import type { ChildrenFunction } from '#typings/index' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' import CustomerContext from '#context/CustomerContext' interface ChildrenProps extends Omit { diff --git a/packages/react-components/src/components/gift_cards/GiftCard.tsx b/packages/react-components/src/components/gift_cards/GiftCard.tsx index 1d1cbe1b..ef71faff 100644 --- a/packages/react-components/src/components/gift_cards/GiftCard.tsx +++ b/packages/react-components/src/components/gift_cards/GiftCard.tsx @@ -1,6 +1,6 @@ import { useRef, useContext, type RefObject, type JSX } from 'react'; import validateFormFields from '#utils/validateFormFields' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' import GiftCardContext from '#context/GiftCardContext' import type { GiftCardI } from '#reducers/GiftCardReducer' import type { BaseState } from '#typings/index' diff --git a/packages/react-components/src/components/line_items/LineItemOption.tsx b/packages/react-components/src/components/line_items/LineItemOption.tsx index f52dca20..dae84f95 100644 --- a/packages/react-components/src/components/line_items/LineItemOption.tsx +++ b/packages/react-components/src/components/line_items/LineItemOption.tsx @@ -1,6 +1,5 @@ import { useContext, type CSSProperties, type JSX } from 'react'; import LineItemOptionChildrenContext from '#context/LineItemOptionChildrenContext' -import map from 'lodash/map' import Parent from '#components/utils/Parent' import type { LineItemOption as LineItemOptionType } from '@commercelayer/sdk' import type { ChildrenFunction } from '#typings/index' @@ -42,11 +41,11 @@ export function LineItemOption(props: Props): JSX.Element { const label = name != null ? lineItemOption?.options?.[name] : '' const components = showAll && isJSON(JSON.stringify(lineItemOption?.options)) ? ( - map(lineItemOption?.options, (value: string, key) => { + Object.entries(lineItemOption?.options ?? {}).map(([key, value]) => { return ( {`${key}:`} - {`${value}`} + {`${value as string}`} ) }) diff --git a/packages/react-components/src/components/orders/OrderListRow.tsx b/packages/react-components/src/components/orders/OrderListRow.tsx index 8b269828..2189f9a3 100644 --- a/packages/react-components/src/components/orders/OrderListRow.tsx +++ b/packages/react-components/src/components/orders/OrderListRow.tsx @@ -6,7 +6,6 @@ import OrderListChildrenContext, { type TableAccessor } from '#context/OrderListChildrenContext' import isDate from '#utils/isDate' -import last from 'lodash/last' import { flexRender, type Row } from '@tanstack/react-table' interface ChildrenProps extends Omit { @@ -43,7 +42,7 @@ export function OrderListRow({ field, children, ...p }: Props): JSX.Element { actionsContainerClassName } = useContext(OrderListChildrenContext) const cell = row?.getVisibleCells().filter((cell) => cell.column.id === field) - const isLastRow = last(row?.getVisibleCells())?.column.id === field + const isLastRow = row?.getVisibleCells().at(-1)?.column.id === field const As = 'td' const ActionRow = (): JSX.Element | null => { return ( diff --git a/packages/react-components/src/components/orders/PlaceOrderButton.tsx b/packages/react-components/src/components/orders/PlaceOrderButton.tsx index 71098b6c..fd26a05b 100644 --- a/packages/react-components/src/components/orders/PlaceOrderButton.tsx +++ b/packages/react-components/src/components/orders/PlaceOrderButton.tsx @@ -1,6 +1,5 @@ /** biome-ignore-all lint/correctness/useExhaustiveDependencies: Avoid infinite loop */ import type { Order } from "@commercelayer/sdk" -import isFunction from "lodash/isFunction" import { type JSX, type MouseEvent, @@ -33,7 +32,7 @@ interface Props /** * The label of the button */ - label?: string | ReactNode + label?: string | ReactNode | (() => ReactNode) /** * The label of the button when it's loading */ @@ -583,7 +582,7 @@ export function PlaceOrderButton(props: Props): JSX.Element { const disabledButton = disabled !== undefined ? disabled : notPermitted const labelButton = isLoading ? loadingLabel - : isFunction(label) + : typeof label === 'function' ? label() : label const parentProps = { diff --git a/packages/react-components/src/components/payment_gateways/AdyenGateway.tsx b/packages/react-components/src/components/payment_gateways/AdyenGateway.tsx index c7153b9d..6240b170 100644 --- a/packages/react-components/src/components/payment_gateways/AdyenGateway.tsx +++ b/packages/react-components/src/components/payment_gateways/AdyenGateway.tsx @@ -1,5 +1,5 @@ import type { StripeElementLocale } from "@stripe/stripe-js" -import isEmpty from "lodash/isEmpty" +import { isEmpty } from "#utils/isEmpty" import { type JSX, useContext } from "react" import type { GatewayBaseType } from "#components/payment_gateways/PaymentGateway" import AdyenPayment from "#components/payment_source/AdyenPayment" diff --git a/packages/react-components/src/components/payment_gateways/BraintreeGateway.tsx b/packages/react-components/src/components/payment_gateways/BraintreeGateway.tsx index ee191f4a..cf3bc2d8 100644 --- a/packages/react-components/src/components/payment_gateways/BraintreeGateway.tsx +++ b/packages/react-components/src/components/payment_gateways/BraintreeGateway.tsx @@ -8,7 +8,7 @@ import PaymentSourceContext from '#context/PaymentSourceContext' import type { PaymentResource } from '#reducers/PaymentMethodReducer' import getCardDetails from '#utils/getCardDetails' import type { StripeElementLocale } from '@stripe/stripe-js' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' import { useContext, type JSX } from 'react'; import PaymentCardsTemplate from '../utils/PaymentCardsTemplate' import { getPaymentAttributes } from '#utils/getPaymentAttributes' diff --git a/packages/react-components/src/components/payment_gateways/CheckoutComGateway.tsx b/packages/react-components/src/components/payment_gateways/CheckoutComGateway.tsx index fe4fae51..0da033d3 100644 --- a/packages/react-components/src/components/payment_gateways/CheckoutComGateway.tsx +++ b/packages/react-components/src/components/payment_gateways/CheckoutComGateway.tsx @@ -1,5 +1,5 @@ import type { StripeElementLocale } from "@stripe/stripe-js" -import isEmpty from "lodash/isEmpty" +import { isEmpty } from "#utils/isEmpty" import React, { type JSX } from "react" import type { GatewayBaseType } from "#components/payment_gateways/PaymentGateway" import CheckoutComPayment from "#components/payment_source/CheckoutComPayment" diff --git a/packages/react-components/src/components/payment_gateways/ExternalGateway.tsx b/packages/react-components/src/components/payment_gateways/ExternalGateway.tsx index a74b5626..7fb5023f 100644 --- a/packages/react-components/src/components/payment_gateways/ExternalGateway.tsx +++ b/packages/react-components/src/components/payment_gateways/ExternalGateway.tsx @@ -11,7 +11,7 @@ import { } from "#reducers/PaymentMethodReducer" import getCardDetails from "#utils/getCardDetails" import type { StripeElementLocale } from "@stripe/stripe-js" -import isEmpty from "lodash/isEmpty" +import { isEmpty } from "#utils/isEmpty" import React, { type JSX } from "react" import PaymentCardsTemplate from "../utils/PaymentCardsTemplate" diff --git a/packages/react-components/src/components/payment_gateways/KlarnaGateway.tsx b/packages/react-components/src/components/payment_gateways/KlarnaGateway.tsx index df9d09fb..de4c1f5f 100644 --- a/packages/react-components/src/components/payment_gateways/KlarnaGateway.tsx +++ b/packages/react-components/src/components/payment_gateways/KlarnaGateway.tsx @@ -10,7 +10,7 @@ import { getPaymentConfig, type PaymentResource } from '#reducers/PaymentMethodReducer' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' import PaymentCardsTemplate from '#components/utils/PaymentCardsTemplate' import getCardDetails from '#utils/getCardDetails' diff --git a/packages/react-components/src/components/payment_gateways/PaypalGateway.tsx b/packages/react-components/src/components/payment_gateways/PaypalGateway.tsx index dae13dd3..1640c997 100644 --- a/packages/react-components/src/components/payment_gateways/PaypalGateway.tsx +++ b/packages/react-components/src/components/payment_gateways/PaypalGateway.tsx @@ -7,7 +7,7 @@ import PaymentSourceContext from '#context/PaymentSourceContext' import type { PaymentResource } from '#reducers/PaymentMethodReducer' import getCardDetails from '#utils/getCardDetails' import { getPaymentAttributes } from '#utils/getPaymentAttributes' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' import { useContext, type JSX } from 'react'; type Props = Partial diff --git a/packages/react-components/src/components/payment_gateways/StripeGateway.tsx b/packages/react-components/src/components/payment_gateways/StripeGateway.tsx index f3b9b69f..37f210b4 100644 --- a/packages/react-components/src/components/payment_gateways/StripeGateway.tsx +++ b/packages/react-components/src/components/payment_gateways/StripeGateway.tsx @@ -1,5 +1,5 @@ import type { StripeElementLocale } from "@stripe/stripe-js" -import isEmpty from "lodash/isEmpty" +import { isEmpty } from "#utils/isEmpty" import { type JSX, useContext } from "react" import type { GatewayBaseType } from "#components/payment_gateways/PaymentGateway" import StripePayment from "#components/payment_source/StripePayment" diff --git a/packages/react-components/src/components/payment_gateways/WireTransferGateway.tsx b/packages/react-components/src/components/payment_gateways/WireTransferGateway.tsx index dcb45767..9214d0ff 100644 --- a/packages/react-components/src/components/payment_gateways/WireTransferGateway.tsx +++ b/packages/react-components/src/components/payment_gateways/WireTransferGateway.tsx @@ -9,7 +9,7 @@ import { type PaymentResource } from '#reducers/PaymentMethodReducer' import getCardDetails from '#utils/getCardDetails' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' import { useContext, type JSX } from 'react'; type Props = GatewayBaseType diff --git a/packages/react-components/src/components/payment_source/BraintreePayment.tsx b/packages/react-components/src/components/payment_source/BraintreePayment.tsx index b1a3118d..c14874b5 100644 --- a/packages/react-components/src/components/payment_source/BraintreePayment.tsx +++ b/packages/react-components/src/components/payment_source/BraintreePayment.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import { type FormEvent, useContext, useEffect, useRef, useState, type JSX } from 'react'; import PaymentMethodContext from '#context/PaymentMethodContext' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' import OrderContext from '#context/OrderContext' import Parent from '#components/utils/Parent' import type { PaymentSourceProps } from './PaymentSource' diff --git a/packages/react-components/src/components/payment_source/PaymentSourceBrandName.tsx b/packages/react-components/src/components/payment_source/PaymentSourceBrandName.tsx index 7375a0b0..3cb77b41 100644 --- a/packages/react-components/src/components/payment_source/PaymentSourceBrandName.tsx +++ b/packages/react-components/src/components/payment_source/PaymentSourceBrandName.tsx @@ -1,7 +1,6 @@ import PaymentSourceContext, { type IconBrand } from '#context/PaymentSourceContext' -import capitalize from 'lodash/capitalize' import { useContext, type JSX } from 'react'; import Parent from '#components/utils/Parent' import type { ChildrenFunction } from '#typings' @@ -24,7 +23,9 @@ export function PaymentSourceBrandName({ const { brand } = useContext(PaymentSourceContext) const { brand: customerCardBrand } = useContext(CustomerPaymentSourceContext) const cardBrand = brand ?? customerCardBrand - const brandName = cardBrand && capitalize(cardBrand.replace(/_|-/gm, ' ')) + const capitalizeStr = (str?: string): string => + str ? str.charAt(0).toUpperCase() + str.slice(1).toLowerCase() : '' + const brandName = cardBrand && capitalizeStr(cardBrand.replace(/_|-/gm, ' ')) const parentProps = { brand: brandName, label, @@ -33,7 +34,7 @@ export function PaymentSourceBrandName({ return children ? ( {children} ) : ( - {label || capitalize(brandName)} + {label || capitalizeStr(brandName)} ) } diff --git a/packages/react-components/src/components/payment_source/PaypalPayment.tsx b/packages/react-components/src/components/payment_source/PaypalPayment.tsx index 09094651..5769fa1f 100644 --- a/packages/react-components/src/components/payment_source/PaypalPayment.tsx +++ b/packages/react-components/src/components/payment_source/PaypalPayment.tsx @@ -1,12 +1,11 @@ import PaymentMethodContext from '#context/PaymentMethodContext' -import isFunction from 'lodash/isFunction' import { type ReactNode, useContext, useEffect, useRef, type JSX } from 'react'; export interface PaypalConfig { return_url: string cancel_url: string infoMessage?: { - text?: string | ReactNode + text?: string | ReactNode | (() => ReactNode) className?: string } } @@ -71,7 +70,7 @@ export function PaypalPayment({
- {isFunction(infoMessage?.text) + {typeof infoMessage?.text === 'function' ? infoMessage?.text() : infoMessage?.text || defaultMessage} diff --git a/packages/react-components/src/components/shipments/ShipmentField.tsx b/packages/react-components/src/components/shipments/ShipmentField.tsx index 7c3be408..3e3aa69e 100644 --- a/packages/react-components/src/components/shipments/ShipmentField.tsx +++ b/packages/react-components/src/components/shipments/ShipmentField.tsx @@ -1,6 +1,5 @@ import { useContext, type JSX } from 'react'; import Parent from '#components/utils/Parent' -import get from 'lodash/get' import type { Shipment } from '@commercelayer/sdk' import ShipmentChildrenContext from '#context/ShipmentChildrenContext' @@ -26,7 +25,10 @@ export function ShipmentField(props: Props): JSX.Element { const { name } = props const { shipment, keyNumber } = useContext(ShipmentChildrenContext) const key = name - const text = key !== 'key_number' ? get(shipment, key) : keyNumber + const text = + key !== 'key_number' + ? (shipment?.[key as keyof Shipment] as string | number | undefined) + : keyNumber const parentProps = { shipment, ...props diff --git a/packages/react-components/src/components/shipments/ShipmentsContainer.tsx b/packages/react-components/src/components/shipments/ShipmentsContainer.tsx index c5597f5e..e0a5cec6 100644 --- a/packages/react-components/src/components/shipments/ShipmentsContainer.tsx +++ b/packages/react-components/src/components/shipments/ShipmentsContainer.tsx @@ -11,7 +11,7 @@ import shipmentReducer, { import OrderContext from '#context/OrderContext' import CommerceLayerContext from '#context/CommerceLayerContext' import type { BaseError } from '#typings/errors' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' interface Props { children: ReactNode diff --git a/packages/react-components/src/components/shipping_methods/ShippingMethod.tsx b/packages/react-components/src/components/shipping_methods/ShippingMethod.tsx index 3fc2f6ae..d8b33b29 100644 --- a/packages/react-components/src/components/shipping_methods/ShippingMethod.tsx +++ b/packages/react-components/src/components/shipping_methods/ShippingMethod.tsx @@ -1,7 +1,7 @@ import { useContext, type ReactNode, useEffect, useState, type JSX } from 'react'; import ShippingMethodChildrenContext from '#context/ShippingMethodChildrenContext' import ShipmentChildrenContext from '#context/ShipmentChildrenContext' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' interface Props { children: ReactNode diff --git a/packages/react-components/src/components/utils/BaseOrderPrice.tsx b/packages/react-components/src/components/utils/BaseOrderPrice.tsx index 99cdfda1..ac66a719 100644 --- a/packages/react-components/src/components/utils/BaseOrderPrice.tsx +++ b/packages/react-components/src/components/utils/BaseOrderPrice.tsx @@ -4,7 +4,7 @@ import Parent from './Parent' import { useState, useEffect, useContext, type JSX } from 'react'; import type { PropsType } from '#utils/PropsType' import type { baseOrderPricePropTypes } from '#typings' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' export type BaseOrderPriceProps = PropsType< typeof baseOrderPricePropTypes, diff --git a/packages/react-components/src/reducers/AddressReducer.ts b/packages/react-components/src/reducers/AddressReducer.ts index 908d3aff..a5c1a190 100644 --- a/packages/react-components/src/reducers/AddressReducer.ts +++ b/packages/react-components/src/reducers/AddressReducer.ts @@ -1,5 +1,4 @@ import type { Address, Order, OrderUpdate } from "@commercelayer/sdk" -import camelCase from "lodash/camelCase" import type { Dispatch } from "react" import type { TResourceError } from "#components/errors/Errors" import type { AddressValuesKeys } from "#context/BillingAddressFormContext" @@ -164,7 +163,7 @@ export const setCloneAddress: SetCloneAddress = (id, resource, dispatch) => { dispatch({ type: "setCloneAddress", payload: { - [`${camelCase(resource)}Id`]: id, + [`${resource.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase())}Id`]: id, }, }) } diff --git a/packages/react-components/src/reducers/GiftCardReducer.ts b/packages/react-components/src/reducers/GiftCardReducer.ts index 5be30cc4..987b22bc 100644 --- a/packages/react-components/src/reducers/GiftCardReducer.ts +++ b/packages/react-components/src/reducers/GiftCardReducer.ts @@ -11,7 +11,7 @@ import type { import type { BaseMetadata } from '#typings' import type { Dispatch } from 'react' import type { CommerceLayerConfig } from '#context/CommerceLayerContext' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' import type { BaseError } from '#typings/errors' import getErrors from '#utils/getErrors' import getSdk from '#utils/getSdk' diff --git a/packages/react-components/src/reducers/OrderReducer.ts b/packages/react-components/src/reducers/OrderReducer.ts index 69ee2206..26d8da20 100644 --- a/packages/react-components/src/reducers/OrderReducer.ts +++ b/packages/react-components/src/reducers/OrderReducer.ts @@ -7,7 +7,7 @@ import type { QueryParamsRetrieve, ResourceUpdate, } from "@commercelayer/sdk" -import isEmpty from "lodash/isEmpty" +import { isEmpty } from "#utils/isEmpty" import type { Dispatch } from "react" import type { CommerceLayerConfig } from "#context/CommerceLayerContext" import type { BaseError } from "#typings/errors" diff --git a/packages/react-components/src/reducers/PlaceOrderReducer.ts b/packages/react-components/src/reducers/PlaceOrderReducer.ts index 5f34a8f9..56a009bc 100644 --- a/packages/react-components/src/reducers/PlaceOrderReducer.ts +++ b/packages/react-components/src/reducers/PlaceOrderReducer.ts @@ -1,5 +1,5 @@ import type { Order, OrderUpdate, StripePayment } from "@commercelayer/sdk" -import isEmpty from "lodash/isEmpty" +import { isEmpty } from "#utils/isEmpty" import type { Dispatch, RefObject } from "react" import type { CommerceLayerConfig } from "#context/CommerceLayerContext" import type { BaseError } from "#typings/errors" diff --git a/packages/react-components/src/utils/addressesManager.ts b/packages/react-components/src/utils/addressesManager.ts index 3858e750..9973b5e0 100644 --- a/packages/react-components/src/utils/addressesManager.ts +++ b/packages/react-components/src/utils/addressesManager.ts @@ -9,7 +9,7 @@ import type { Order, OrderUpdate, } from "@commercelayer/sdk" -import isEmpty from "lodash/isEmpty" +import { isEmpty } from "#utils/isEmpty" import { type AddressField, addressFields } from "#reducers/AddressReducer" import type { TCustomerAddress } from "#reducers/CustomerReducer" import type { BaseError } from "#typings/errors" diff --git a/packages/react-components/src/utils/countryStateCity.ts b/packages/react-components/src/utils/countryStateCity.ts index a15c4e6e..ffd2a45c 100644 --- a/packages/react-components/src/utils/countryStateCity.ts +++ b/packages/react-components/src/utils/countryStateCity.ts @@ -1,4 +1,4 @@ -import isEmpty from "lodash/isEmpty" +import { isEmpty } from "#utils/isEmpty" /** * Validate the list of countries the user can optionally pass or returns our default list diff --git a/packages/react-components/src/utils/getAmount.ts b/packages/react-components/src/utils/getAmount.ts index c4993d40..5b684b89 100644 --- a/packages/react-components/src/utils/getAmount.ts +++ b/packages/react-components/src/utils/getAmount.ts @@ -1,5 +1,3 @@ -import keys from 'lodash/keys' - export type GetAmountInterface = ( base: string, type: string, @@ -15,7 +13,7 @@ export default function getAmount(args: { }): T extends number ? number : string { const { format, type, obj, base } = args let v: any - keys(obj).forEach((k: string) => { + Object.keys(obj).forEach((k: string) => { const key = k.toLowerCase() const typeOne = `${format}_${type}_${base}`.toLowerCase() const typeTwo = `${type}_${base}_${format}`.toLowerCase() diff --git a/packages/react-components/src/utils/getErrors.ts b/packages/react-components/src/utils/getErrors.ts index 267ec497..ec1d60d8 100644 --- a/packages/react-components/src/utils/getErrors.ts +++ b/packages/react-components/src/utils/getErrors.ts @@ -1,7 +1,5 @@ import type { TResourceError } from '#components/errors/Errors' import type { BaseError, TAPIError } from '#typings/errors' -import type { ValueIteratee } from 'lodash' -import differenceBy from 'lodash/differenceBy' import type { Dispatch } from 'react' interface GetErrorsParams { @@ -27,11 +25,13 @@ export default function getErrors({ }) } +type FilterBy = keyof BaseError | ((item: BaseError) => unknown) + interface SetErrorsArgs { currentErrors?: BaseError[] newErrors?: BaseError[] dispatch?: D - filterBy?: ValueIteratee + filterBy?: FilterBy } export function setErrors>({ @@ -40,7 +40,14 @@ export function setErrors>({ dispatch, filterBy = 'code' }: SetErrorsArgs): BaseError[] { - const errorsDifference = differenceBy(currentErrors, newErrors, filterBy) + const getValue = + typeof filterBy === 'function' + ? filterBy + : (item: BaseError) => item[filterBy as keyof BaseError] + const excludeValues = new Set(newErrors.map(getValue)) + const errorsDifference = currentErrors.filter( + (item) => !excludeValues.has(getValue(item)) + ) const mergeErrors = currentErrors?.length === 0 ? newErrors : errorsDifference const errors = [...(currentErrors || []), ...mergeErrors] if (dispatch != null) { diff --git a/packages/react-components/src/utils/getPrices.tsx b/packages/react-components/src/utils/getPrices.tsx index d2c82566..0c61ad41 100644 --- a/packages/react-components/src/utils/getPrices.tsx +++ b/packages/react-components/src/utils/getPrices.tsx @@ -1,4 +1,3 @@ -import { isEmpty, first, isArray, has } from 'lodash' import type { Price } from '@commercelayer/sdk' import PriceTemplate, { type PTemplateProps @@ -11,15 +10,15 @@ export function getPriceByCode( code: string = '' ): Price | undefined { return code - ? first(skuPrices.filter((p) => p.currency_code === code)) - : first(skuPrices) + ? skuPrices.filter((p) => p.currency_code === code)[0] + : skuPrices[0] } export function getPricesComponent( skuPrices: Price[], props: PTemplateProps ): JSX.Element[] | JSX.Element { - if (isEmpty(skuPrices)) { + if (skuPrices.length === 0) { return } return skuPrices.map((p, k) => { @@ -45,10 +44,10 @@ export default function getPrices

( prices: P[] ): Record { const obj: Record = {} - if (isArray(prices)) { + if (Array.isArray(prices)) { prices.forEach((p) => { const sku = p?.sku_code ?? '' - if (has(obj, sku)) { + if (Object.hasOwn(obj, sku)) { obj[sku].push(p) } else { obj[sku] = [p] diff --git a/packages/react-components/src/utils/isEmpty.ts b/packages/react-components/src/utils/isEmpty.ts index 500aae4d..7d130c02 100644 --- a/packages/react-components/src/utils/isEmpty.ts +++ b/packages/react-components/src/utils/isEmpty.ts @@ -1,13 +1,7 @@ -export function isEmpty(value: V): boolean { +export function isEmpty(value: unknown): boolean { if (value == null) return true - if (Array.isArray(value)) { - return value.length === 0 - } - if (typeof value === 'string') { - return value.length === 0 - } - if (typeof value === 'object') { - return Object.keys(value).length === 0 - } - throw new Error('Invalid value for isEmpty function') + if (typeof value === 'string' || Array.isArray(value)) return value.length === 0 + if (value instanceof Map || value instanceof Set) return value.size === 0 + if (typeof value === 'object') return Object.keys(value as object).length === 0 + return false } diff --git a/packages/react-components/src/utils/promisify.ts b/packages/react-components/src/utils/promisify.ts index 7ad5b07a..19d336a8 100644 --- a/packages/react-components/src/utils/promisify.ts +++ b/packages/react-components/src/utils/promisify.ts @@ -1,5 +1,4 @@ /* eslint-disable n/no-callback-literal */ -import isFunction from 'lodash/isFunction' export default async function promisify(cb: any, params?: any): Promise { return await new Promise((resolve, reject) => { @@ -8,7 +7,7 @@ export default async function promisify(cb: any, params?: any): Promise { if (err) reject(err) resolve(res) }) - else if (isFunction(cb?.tokenize)) { + else if (typeof cb?.tokenize === 'function') { cb?.tokenize((err: any, payload: any) => { if (err) reject(err) resolve(payload) diff --git a/packages/react-components/src/utils/shipments.ts b/packages/react-components/src/utils/shipments.ts index 2a13c711..2cb1fa59 100644 --- a/packages/react-components/src/utils/shipments.ts +++ b/packages/react-components/src/utils/shipments.ts @@ -1,12 +1,9 @@ import type { LineItem, Shipment } from '@commercelayer/sdk' -import compact from 'lodash/compact' -import isEmpty from 'lodash/isEmpty' +import { isEmpty } from '#utils/isEmpty' export function shipmentsFilled(shipments: Shipment[]): boolean { - const filled = compact( - shipments.filter((shipment) => !isEmpty(shipment.shipping_method)) - ) - return !isEmpty(filled) + const filled = shipments.filter((shipment) => !isEmpty(shipment.shipping_method)) + return filled.length > 0 } export function isDoNotShip(lineItems?: LineItem[] | null): boolean { diff --git a/packages/react-components/src/utils/validateFormFields.ts b/packages/react-components/src/utils/validateFormFields.ts index fb393be1..8bc9b43e 100644 --- a/packages/react-components/src/utils/validateFormFields.ts +++ b/packages/react-components/src/utils/validateFormFields.ts @@ -1,11 +1,5 @@ -// TODO: Remove lodash - import type { AddressCreate } from "@commercelayer/sdk" -import isEmpty from "lodash/isEmpty" -import isString from "lodash/isString" -import keys from "lodash/keys" -import map from "lodash/map" -import without from "lodash/without" +import { isEmpty } from "#utils/isEmpty" import type { TResourceError } from "#components/errors/Errors" import { type AddressField, addressFields } from "#reducers/AddressReducer" import type { AddressInputName } from "#typings" @@ -49,7 +43,7 @@ export const validateValue: ValidateValue = (val, name, type, resource) => { resource, } } - if (type === "email" && isString(val) && !val.match(EMAIL_PATTERN)) { + if (type === "email" && typeof val === 'string' && !val.match(EMAIL_PATTERN)) { return { field: name, code: "VALIDATION_ERROR", @@ -67,7 +61,7 @@ const validateFormFields: ValidateFormFields = ( ) => { const errors: BaseError[] = [] let values = { metadata: {} } - map(fields, (v: FormField) => { + Array.from(fields).forEach((v: FormField) => { const isTick = "checked" in v const val = isTick || (v.value === "on" ? false : v.value) const attrName = v.getAttribute("name") @@ -96,18 +90,17 @@ export function fieldsExist( schema: Array = addressFields, ): boolean { if (!address.business) { - const required = without(schema, "line_2", "company", "state_code") - const validAddress = keys(address).filter((k) => required.includes(k)) + const required = schema.filter( + (v) => !["line_2", "company", "state_code"].includes(v), + ) + const validAddress = Object.keys(address).filter((k) => required.includes(k)) return required.length > validAddress.length } - const required = without( - schema, - "first_name", - "last_name", - "line_2", - "state_code", + const required = schema.filter( + (v) => + !["first_name", "last_name", "line_2", "state_code"].includes(v), ) - const validAddress = keys(address).filter((k) => required.includes(k)) + const validAddress = Object.keys(address).filter((k) => required.includes(k)) return required.length > validAddress.length } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 58d06c3a..3dc8d319 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -362,9 +362,6 @@ importers: jwt-decode: specifier: ^4.0.0 version: 4.0.0 - lodash: - specifier: ^4.17.21 - version: 4.17.21 rapid-form: specifier: 3.1.0 version: 3.1.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -390,9 +387,6 @@ importers: '@types/braintree-web': specifier: ^3.96.17 version: 3.96.17 - '@types/lodash': - specifier: ^4.17.21 - version: 4.17.23 '@types/node': specifier: ^25.0.3 version: 25.0.8 @@ -2765,9 +2759,6 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/lodash@4.17.23': - resolution: {integrity: sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==} - '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} @@ -9131,8 +9122,6 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/lodash@4.17.23': {} - '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3