From 6cba952299c7e1f527e9ce6953697980a4dd75cf Mon Sep 17 00:00:00 2001 From: jialecl Date: Wed, 14 Oct 2026 09:10:44 +0200 Subject: [PATCH 01/18] Types exported --- packages/lib/src/accordion/Accordion.tsx | 8 +-- packages/lib/src/accordion/types.ts | 6 +-- .../src/action-icon/ActionIcon.stories.tsx | 28 +++++------ packages/lib/src/action-icon/ActionIcon.tsx | 18 +++---- packages/lib/src/action-icon/types.ts | 15 ++---- packages/lib/src/action-icon/utils.ts | 14 +++--- packages/lib/src/alert/Actions.tsx | 4 +- packages/lib/src/alert/Alert.tsx | 16 +++--- packages/lib/src/alert/types.ts | 18 +++---- packages/lib/src/avatar/types.ts | 17 +++---- packages/lib/src/badge/Badge.tsx | 22 ++++---- packages/lib/src/badge/types.ts | 50 +++++++++---------- packages/lib/src/base-menu/types.ts | 2 +- packages/lib/src/breadcrumbs/Breadcrumbs.tsx | 2 +- packages/lib/src/breadcrumbs/Item.tsx | 6 +-- packages/lib/src/breadcrumbs/types.ts | 20 ++++---- .../lib/src/bulleted-list/BulletedList.tsx | 6 +-- packages/lib/src/bulleted-list/types.ts | 12 ++--- packages/lib/src/button/Button.tsx | 16 +++--- packages/lib/src/button/types.ts | 18 +++---- packages/lib/src/button/utils.ts | 12 +++-- packages/lib/src/checkbox/types.ts | 2 +- packages/lib/src/chip/types.ts | 2 +- packages/lib/src/common/types.ts | 22 ++++++++ packages/lib/src/common/utils.ts | 12 +---- packages/lib/src/container/Container.tsx | 4 +- packages/lib/src/container/types.ts | 31 ++++-------- packages/lib/src/date-input/types.ts | 2 +- packages/lib/src/dropdown/types.ts | 2 +- packages/lib/src/file-input/types.ts | 2 +- packages/lib/src/footer/types.ts | 2 +- packages/lib/src/global.d.ts | 2 + packages/lib/src/heading/types.ts | 2 +- packages/lib/src/index.ts | 26 ++++++++++ packages/lib/src/layout/types.ts | 2 +- packages/lib/src/link/types.ts | 2 +- packages/lib/src/nav-tabs/types.ts | 2 +- packages/lib/src/number-input/types.ts | 2 +- packages/lib/src/password-input/types.ts | 2 +- packages/lib/src/progress-bar/types.ts | 11 +--- packages/lib/src/resultset-table/types.ts | 2 +- packages/lib/src/select/types.ts | 2 +- packages/lib/src/slider/types.ts | 2 +- packages/lib/src/spinner/types.ts | 2 +- packages/lib/src/switch/types.ts | 2 +- packages/lib/src/table/types.ts | 2 +- packages/lib/src/tabs/types.ts | 2 +- packages/lib/src/text-input/types.ts | 2 +- packages/lib/src/textarea/types.ts | 2 +- packages/lib/src/toast/types.ts | 2 +- packages/lib/src/toggle-group/types.ts | 2 +- packages/lib/src/wizard/types.ts | 2 +- 52 files changed, 238 insertions(+), 228 deletions(-) create mode 100644 packages/lib/src/common/types.ts diff --git a/packages/lib/src/accordion/Accordion.tsx b/packages/lib/src/accordion/Accordion.tsx index 1e7466c2e7..9cc4e2e631 100644 --- a/packages/lib/src/accordion/Accordion.tsx +++ b/packages/lib/src/accordion/Accordion.tsx @@ -2,15 +2,15 @@ import { JSX, Children, useCallback, useMemo, useState } from "react"; import styled from "@emotion/styled"; import { getMargin } from "../common/utils"; import { spaces } from "../common/variables"; -import AccordionPropsType, { AccordionContextProps } from "./types"; +import { AccordionProps, AccordionContextProps } from "./types"; import AccordionContext from "./AccordionContext"; import AccordionItem from "./AccordionItem"; -const calculateWidth = (margin: AccordionPropsType["margin"]) => +const calculateWidth = (margin: AccordionProps["margin"]) => `calc(100% - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})`; const AccordionContainer = styled.div<{ - margin: AccordionPropsType["margin"]; + margin: AccordionProps["margin"]; }>` width: ${(props) => calculateWidth(props.margin)}; margin: ${({ margin }) => (margin && typeof margin !== "object" ? spaces[margin] : "var(--spacing-padding-none)")}; @@ -74,7 +74,7 @@ const AccordionItemWithProvider = ({ return {child}; }; -const DxcAccordion = (props: AccordionPropsType): JSX.Element => { +const DxcAccordion = (props: AccordionProps): JSX.Element => { const { children, defaultIndexActive, independent, indexActive, margin, onActiveChange } = props; const [innerIndexActive, setInnerIndexActive] = useState( diff --git a/packages/lib/src/accordion/types.ts b/packages/lib/src/accordion/types.ts index 8f44b489ad..2d6afdf098 100644 --- a/packages/lib/src/accordion/types.ts +++ b/packages/lib/src/accordion/types.ts @@ -1,5 +1,5 @@ import { ReactNode, ReactElement } from "react"; -import { Margin, SVG, Space } from "../common/utils"; +import { Margin, PrettifyTypes, SVG, Space } from "../common/types"; export type AccordionItemProps = { /** @@ -103,7 +103,7 @@ type NonIndependentProps = CommonProps & { onActiveChange?: (index: number[]) => void; }; -type Props = IndependentProps | NonIndependentProps; +export type AccordionProps = PrettifyTypes; export type AccordionContextProps = { index: number; @@ -111,5 +111,3 @@ export type AccordionContextProps = { handlerActiveChange?: (index: number | number[]) => void; independent?: boolean; }; - -export default Props; diff --git a/packages/lib/src/action-icon/ActionIcon.stories.tsx b/packages/lib/src/action-icon/ActionIcon.stories.tsx index 86a96bfc76..e49938ec8e 100644 --- a/packages/lib/src/action-icon/ActionIcon.stories.tsx +++ b/packages/lib/src/action-icon/ActionIcon.stories.tsx @@ -5,7 +5,7 @@ import DxcActionIcon from "./ActionIcon"; import DxcFlex from "../flex/Flex"; import Title from "../../.storybook/components/Title"; import ExampleContainer, { PseudoState } from "../../.storybook/components/ExampleContainer"; -import { ActionIconPropTypes, Status } from "./types"; +import { ActionIconProps, Status } from "./types"; export default { title: "ActionIcon", @@ -17,10 +17,10 @@ type Story = StoryObj; type GroupingKey = "size" | "shape" | "color" | "statusPosition" | "statusMode" | "pseudoState"; type ActionIconRowProps = { - sizes?: ActionIconPropTypes["size"][]; - shapes?: ActionIconPropTypes["shape"][]; - colors?: ActionIconPropTypes["color"][]; - icon?: ActionIconPropTypes["icon"]; + sizes?: ActionIconProps["size"][]; + shapes?: ActionIconProps["shape"][]; + colors?: ActionIconProps["color"][]; + icon?: ActionIconProps["icon"]; statusModes?: Status["mode"][]; statusPositions?: (Status["position"] | undefined)[]; pseudoStates?: (PseudoState | "disabled" | undefined)[]; @@ -58,9 +58,9 @@ const ActionIconRow = ({ const renderGroup = ( level: number, filters: { - size?: ActionIconPropTypes["size"]; - shape?: ActionIconPropTypes["shape"]; - color?: ActionIconPropTypes["color"]; + size?: ActionIconProps["size"]; + shape?: ActionIconProps["shape"]; + color?: ActionIconProps["color"]; statusMode?: Status["mode"]; statusPosition?: Status["position"]; pseudoState?: PseudoState | "disabled"; @@ -117,9 +117,9 @@ const ActionIconRow = ({ return values.map((value) => { const newFilters = { ...filters }; - if (key === "size") newFilters.size = value as ActionIconPropTypes["size"]; - else if (key === "shape") newFilters.shape = value as ActionIconPropTypes["shape"]; - else if (key === "color") newFilters.color = value as ActionIconPropTypes["color"]; + if (key === "size") newFilters.size = value as ActionIconProps["size"]; + else if (key === "shape") newFilters.shape = value as ActionIconProps["shape"]; + else if (key === "color") newFilters.color = value as ActionIconProps["color"]; else if (key === "statusPosition") newFilters.statusPosition = value as Status["position"]; else if (key === "statusMode") newFilters.statusMode = value as Status["mode"]; else if (key === "pseudoState") newFilters.pseudoState = value as PseudoState | "disabled"; @@ -156,7 +156,7 @@ export const Colors: Story = { @@ -167,10 +167,10 @@ export const PseudoStates: Story = { render: () => ( <> - <DxcActionIcon color="transparent" icon="settings" onClick={() => console.log("hello")} /> + <DxcActionIcon icon="settings" onClick={() => console.log("hello")} /> <ActionIconRow - colors={["transparent"]} + colors={undefined} sizes={["xsmall", "small", "medium", "large", "xlarge", "xxlarge"]} shapes={["square"]} statusModes={["success"]} diff --git a/packages/lib/src/action-icon/ActionIcon.tsx b/packages/lib/src/action-icon/ActionIcon.tsx index 1442ed9c62..b2341f272c 100644 --- a/packages/lib/src/action-icon/ActionIcon.tsx +++ b/packages/lib/src/action-icon/ActionIcon.tsx @@ -1,6 +1,6 @@ import styled from "@emotion/styled"; import { css } from "@emotion/react"; -import { ActionIconPropTypes } from "./types"; +import { ActionIconProps } from "./types"; import { getBackgroundColor, getBorderRadius, getColor, getIconSize, getOutlineWidth, getSize } from "./utils"; import DxcIcon from "../icon/Icon"; import { Tooltip } from "../tooltip/Tooltip"; @@ -8,10 +8,10 @@ import { Tooltip } from "../tooltip/Tooltip"; const ActionIconContainer = styled.div< { hasAction?: boolean; - shape: ActionIconPropTypes["shape"]; - size: ActionIconPropTypes["size"]; - disabled?: ActionIconPropTypes["disabled"]; - color: ActionIconPropTypes["color"]; + shape: ActionIconProps["shape"]; + size: ActionIconProps["size"]; + disabled?: ActionIconProps["disabled"]; + color?: ActionIconProps["color"]; } & React.AnchorHTMLAttributes<HTMLAnchorElement> >` /* Reset button default styles when rendered as button */ @@ -62,7 +62,7 @@ const ActionIconContainer = styled.div< const IconContainerWrapper = styled.div<{ hasAction?: boolean; - disabled: ActionIconPropTypes["disabled"]; + disabled: ActionIconProps["disabled"]; }>` height: 100%; width: 100%; @@ -82,7 +82,7 @@ const IconContainerWrapper = styled.div<{ `} `; -export const IconContainer = styled.div<{ size: ActionIconPropTypes["size"] }>` +export const IconContainer = styled.div<{ size: ActionIconProps["size"] }>` display: flex; justify-content: center; align-items: center; @@ -100,7 +100,7 @@ export const IconContainer = styled.div<{ size: ActionIconPropTypes["size"] }>` const ForwardedActionIcon = ({ ariaLabel, content, - color = "transparent", + color = undefined, disabled = false, icon, linkHref, @@ -110,7 +110,7 @@ const ForwardedActionIcon = ({ size = "medium", tabIndex = 0, title, -}: ActionIconPropTypes) => { +}: ActionIconProps) => { return ( <Tooltip label={title}> <ActionIconContainer diff --git a/packages/lib/src/action-icon/types.ts b/packages/lib/src/action-icon/types.ts index ea46592a7d..61786e2ce0 100644 --- a/packages/lib/src/action-icon/types.ts +++ b/packages/lib/src/action-icon/types.ts @@ -1,21 +1,12 @@ import { MouseEvent, ReactNode, Ref } from "react"; -import { SVG } from "../common/utils"; +import { SVG, Color, Shape, Size } from "../common/types"; export type RefType = HTMLDivElement; - -type Size = "xsmall" | "small" | "medium" | "large" | "xlarge" | "xxlarge"; -type Shape = "circle" | "square"; -type Color = - "primary" | "secondary" | "tertiary" | "success" | "info" | "neutral" | "warning" | "error" | "transparent"; export interface Status { mode: "default" | "info" | "success" | "warning" | "error"; position: "top" | "bottom"; } -export type ActionIconPropTypes = - | (CommonProps & { content: ReactNode; icon?: string | SVG }) - | (CommonProps & { content?: ReactNode; icon: string | SVG }); - type CommonProps = { /** * Text to be used as aria-label for the Action Icon. It is recommended to provide this prop when using the onClick or linkHref properties and no title is provided. @@ -58,3 +49,7 @@ type CommonProps = { */ title?: string; }; + +export type ActionIconProps = + | (CommonProps & { content: ReactNode; icon?: string | SVG }) + | (CommonProps & { content?: ReactNode; icon: string | SVG }); diff --git a/packages/lib/src/action-icon/utils.ts b/packages/lib/src/action-icon/utils.ts index 73d6287c80..d43f0487f3 100644 --- a/packages/lib/src/action-icon/utils.ts +++ b/packages/lib/src/action-icon/utils.ts @@ -1,4 +1,4 @@ -import { ActionIconPropTypes } from "./types"; +import { ActionIconProps } from "./types"; const contextualColorMap = { primary: { @@ -75,13 +75,13 @@ const outlineWidthMap = { xxlarge: "var(--border-width-l)", }; -export const getColor = (color: ActionIconPropTypes["color"]) => +export const getColor = (color: ActionIconProps["color"]) => color && contextualColorMap[color] ? contextualColorMap[color].text : contextualColorMap.transparent.text; -export const getBackgroundColor = (color: ActionIconPropTypes["color"]) => +export const getBackgroundColor = (color: ActionIconProps["color"]) => color && contextualColorMap[color] ? contextualColorMap[color].background : contextualColorMap.transparent.background; -export const getBorderRadius = (shape: ActionIconPropTypes["shape"], size: ActionIconPropTypes["size"]) => { +export const getBorderRadius = (shape: ActionIconProps["shape"], size: ActionIconProps["size"]) => { if (shape === "circle") { return "100%"; } @@ -91,10 +91,10 @@ export const getBorderRadius = (shape: ActionIconPropTypes["shape"], size: Actio return "100%"; }; -export const getSize = (size: ActionIconPropTypes["size"]) => (size && sizeMap[size] ? sizeMap[size] : "40px"); +export const getSize = (size: ActionIconProps["size"]) => (size && sizeMap[size] ? sizeMap[size] : "40px"); -export const getIconSize = (size: ActionIconPropTypes["size"]) => +export const getIconSize = (size: ActionIconProps["size"]) => size && iconSizeMap[size] ? iconSizeMap[size] : "var(--height-s)"; -export const getOutlineWidth = (size: ActionIconPropTypes["size"]) => +export const getOutlineWidth = (size: ActionIconProps["size"]) => size && outlineWidthMap[size] ? outlineWidthMap[size] : "var(--border-width-m)"; diff --git a/packages/lib/src/alert/Actions.tsx b/packages/lib/src/alert/Actions.tsx index 65ef62cfb8..80eb04af0b 100644 --- a/packages/lib/src/alert/Actions.tsx +++ b/packages/lib/src/alert/Actions.tsx @@ -1,7 +1,7 @@ import { memo } from "react"; import DxcButton from "../button/Button"; import DxcFlex from "../flex/Flex"; -import AlertPropsType from "./types"; +import { AlertProps } from "./types"; const Actions = memo( ({ @@ -9,7 +9,7 @@ const Actions = memo( primaryAction, secondaryAction, semantic, - }: Pick<AlertPropsType, "mode" | "primaryAction" | "secondaryAction" | "semantic">) => + }: Pick<AlertProps, "mode" | "primaryAction" | "secondaryAction" | "semantic">) => (primaryAction != null || secondaryAction != null) && ( <DxcFlex gap="var(--spacing-gap-s)" alignSelf={mode === "inline" || mode === "modal" ? "flex-end" : undefined}> {secondaryAction?.onClick && ( diff --git a/packages/lib/src/alert/Alert.tsx b/packages/lib/src/alert/Alert.tsx index 4c5f0d997e..2ce9104a91 100644 --- a/packages/lib/src/alert/Alert.tsx +++ b/packages/lib/src/alert/Alert.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; import { css } from "@emotion/react"; import { useState, useId, useEffect, useCallback, use, useMemo } from "react"; -import AlertPropsType from "./types"; +import { AlertProps } from "./types"; import DxcIcon from "../icon/Icon"; import DxcDivider from "../divider/Divider"; import DxcActionIcon from "../action-icon/ActionIcon"; @@ -11,8 +11,8 @@ import ModalAlertWrapper from "./ModalAlertWrapper"; import { HalstackLanguageContext } from "../HalstackContext"; const AlertContainer = styled.div<{ - semantic: AlertPropsType["semantic"]; - mode: AlertPropsType["mode"]; + semantic: AlertProps["semantic"]; + mode: AlertProps["mode"]; }>` box-sizing: border-box; display: flex; @@ -35,7 +35,7 @@ const AlertContainer = styled.div<{ overflow: hidden; `; -const TitleContainer = styled.div<{ mode: AlertPropsType["mode"]; semantic: AlertPropsType["semantic"] }>` +const TitleContainer = styled.div<{ mode: AlertProps["mode"]; semantic: AlertProps["semantic"] }>` flex-grow: 1; display: flex; align-items: center; @@ -55,13 +55,13 @@ const typographyStyles = css` font-weight: var(--typography-helper-text-regular); `; -const Title = styled.span<{ mode: AlertPropsType["mode"] }>` +const Title = styled.span<{ mode: AlertProps["mode"] }>` ${typographyStyles} font-size: ${(props) => (props.mode === "modal" ? "var(--typography-title-xl)" : "var(--typography-title-s)")}; font-weight: var(--typography-title-bold); `; -const Message = styled.div<{ mode: AlertPropsType["mode"] }>` +const Message = styled.div<{ mode: AlertProps["mode"] }>` ${typographyStyles} white-space: ${(props) => props.mode === "banner" && "nowrap"}; text-overflow: ${(props) => props.mode === "banner" && "ellipsis"}; @@ -79,7 +79,7 @@ const NavigationText = styled.span` font-size: var(--typography-helper-text-s); `; -const getIcon = (semantic: AlertPropsType["semantic"]) => { +const getIcon = (semantic: AlertProps["semantic"]) => { switch (semantic) { case "info": return <DxcIcon icon="filled_info" />; @@ -100,7 +100,7 @@ const DxcAlert = ({ secondaryAction, semantic = "info", title = "", -}: AlertPropsType) => { +}: AlertProps) => { const messages = useMemo(() => (Array.isArray(message) ? message : [message]), [message]); const [currentIndex, setCurrentIndex] = useState(0); diff --git a/packages/lib/src/alert/types.ts b/packages/lib/src/alert/types.ts index b348298997..a4adce5f12 100644 --- a/packages/lib/src/alert/types.ts +++ b/packages/lib/src/alert/types.ts @@ -1,7 +1,7 @@ import { ReactNode } from "react"; -import { SVG } from "../common/utils"; +import { PrettifyTypes, SVG } from "../common/types"; -type Action = { +export type AlertAction = { /** * The icon of the action. It can be a string with the name of the icon or an SVG component. */ @@ -16,7 +16,7 @@ type Action = { onClick: () => void; }; -type Message = { +export type AlertMessage = { /** * The function that will be executed when the user clicks on the close action button. */ @@ -39,11 +39,11 @@ type CommonProps = { /** * Primary action of the alert. */ - primaryAction?: Action; + primaryAction?: AlertAction; /** * Secondary action of the alert. */ - secondaryAction?: Action; + secondaryAction?: AlertAction; /** * Specifies the semantic meaning of the alert. */ @@ -64,7 +64,7 @@ type ModeSpecificProps = * and the presence of the onClose attribute is mandatory, since the management of the closing * of the alert relies completely on the user. */ - message?: Message | Message[]; + message?: AlertMessage | AlertMessage[]; /** * The mode of the alert. */ @@ -79,19 +79,17 @@ type ModeSpecificProps = * and the presence of the onClose attribute is mandatory, since the management of the closing * of the alert relies completely on the user. */ - message: Required<Message>; + message: Required<AlertMessage>; /** * The mode of the alert. */ mode: "modal"; }; -type Props = CommonProps & ModeSpecificProps; +export type AlertProps = PrettifyTypes<CommonProps & ModeSpecificProps>; export type ModalAlertWrapperProps = { condition: boolean; onClose?: () => void; children: ReactNode; }; - -export default Props; diff --git a/packages/lib/src/avatar/types.ts b/packages/lib/src/avatar/types.ts index 1f415bb4bf..aaef6afb41 100644 --- a/packages/lib/src/avatar/types.ts +++ b/packages/lib/src/avatar/types.ts @@ -1,15 +1,12 @@ import { Ref } from "react"; -import { SVG } from "../common/utils"; +import { SVG, Color, Size, Shape } from "../common/types"; -type Size = "xsmall" | "small" | "medium" | "large" | "xlarge" | "xxlarge"; -type Shape = "circle" | "square"; -type Color = "primary" | "secondary" | "tertiary" | "success" | "info" | "neutral" | "warning" | "error"; -export interface Status { +export type AvatarStatus = { mode: "default" | "info" | "success" | "warning" | "error"; position: "top" | "bottom"; -} +}; -type Props = { +export type AvatarProps = { /** * Affects the visual style of the avatar. It can be used following semantic purposes or not. */ @@ -63,7 +60,7 @@ type Props = { * Defines the color of the status indicator displayed on the avatar and where it will be placed. * If not provided, no indicator will be rendered. */ - status?: Status; + status?: AvatarStatus; /** * Value of the tabindex attribute. It will only apply when the onClick property is passed. */ @@ -95,7 +92,5 @@ export type ContentType = { initials: string; icon?: string | SVG; color: Color; - status?: Status; + status?: AvatarStatus; }; - -export default Props; diff --git a/packages/lib/src/badge/Badge.tsx b/packages/lib/src/badge/Badge.tsx index 1b99d52519..03f5dbecfd 100644 --- a/packages/lib/src/badge/Badge.tsx +++ b/packages/lib/src/badge/Badge.tsx @@ -1,5 +1,5 @@ import styled from "@emotion/styled"; -import BadgePropsType from "./types"; +import { BadgeProps } from "./types"; import DxcIcon from "../icon/Icon"; import { Tooltip } from "../tooltip/Tooltip"; @@ -82,13 +82,13 @@ const sizeMap = { }, }; -const getColor = (mode: BadgePropsType["mode"], color: BadgePropsType["color"]) => +const getColor = (mode: BadgeProps["mode"], color: BadgeProps["color"]) => mode === "contextual" && color ? contextualColorMap[color].text : notificationColor.text; -const getBackgroundColor = (mode: BadgePropsType["mode"], color: BadgePropsType["color"]) => +const getBackgroundColor = (mode: BadgeProps["mode"], color: BadgeProps["color"]) => mode === "contextual" && color ? contextualColorMap[color].background : notificationColor.background; -const getPadding = (mode: BadgePropsType["mode"], size: BadgePropsType["size"], label: BadgePropsType["label"]) => +const getPadding = (mode: BadgeProps["mode"], size: BadgeProps["size"], label: BadgeProps["label"]) => size && (mode === "contextual" ? sizeMap[size].padding.contextual @@ -97,10 +97,10 @@ const getPadding = (mode: BadgePropsType["mode"], size: BadgePropsType["size"], : sizeMap[size].padding.notification); const BadgeContainer = styled.div<{ - label: BadgePropsType["label"]; - mode: BadgePropsType["mode"]; - color: BadgePropsType["color"]; - size: BadgePropsType["size"]; + label: BadgeProps["label"]; + mode: BadgeProps["mode"]; + color: BadgeProps["color"]; + size: BadgeProps["size"]; }>` box-sizing: border-box; border-radius: ${(props) => props.size && sizeMap[props.size].borderRadius}; @@ -117,7 +117,7 @@ const BadgeContainer = styled.div<{ color: ${(props) => getColor(props.mode, props.color)}; `; -const IconContainer = styled.div<{ size: BadgePropsType["size"] }>` +const IconContainer = styled.div<{ size: BadgeProps["size"] }>` display: flex; font-size: ${(props) => props.size && sizeMap[props.size].iconSize}; @@ -127,7 +127,7 @@ const IconContainer = styled.div<{ size: BadgePropsType["size"] }>` } `; -const Label = styled.span<{ size: BadgePropsType["size"] }>` +const Label = styled.span<{ size: BadgeProps["size"] }>` font-family: var(--typography-font-family); font-size: ${(props) => props.size && sizeMap[props.size].fontSize}; font-style: normal; @@ -145,7 +145,7 @@ const DxcBadge = ({ notificationLimit = 99, ref, size = "medium", -}: BadgePropsType) => ( +}: BadgeProps) => ( <Tooltip label={title}> <BadgeContainer label={label} diff --git a/packages/lib/src/badge/types.ts b/packages/lib/src/badge/types.ts index c77c5029f1..b1be76d723 100644 --- a/packages/lib/src/badge/types.ts +++ b/packages/lib/src/badge/types.ts @@ -1,6 +1,25 @@ -import { SVG } from "../common/utils"; +import { Color, PrettifyTypes, SVG } from "../common/types"; -export type ContextualProps = { +export type CommonProps = { + /** + * Text representing advisory information related to the badge. Under the hood, this prop also serves as an accessible label for the component. + */ + title?: string; + /** + * Material Symbol name or SVG element used as the icon that will be placed next to the badge label in contextual mode. + */ + icon?: string | SVG; + /** + * Ref to be forwarded to the badge container element. + */ + ref?: React.Ref<HTMLDivElement>; + /** + * Size of the component. + */ + size?: "small" | "medium" | "large"; +}; + +export type ContextualBadgeProps = CommonProps & { /** * Text to be placed in the badge. */ @@ -16,10 +35,10 @@ export type ContextualProps = { /** * Affects the visual style of the badge. It can be used following semantic purposes or not. */ - color?: "primary" | "secondary" | "tertiary" | "success" | "info" | "neutral" | "warning" | "error"; + color?: Color; }; -export type NotificationProps = { +export type NotificationBadgeProps = CommonProps & { /** * Text to be placed in the badge. */ @@ -38,25 +57,4 @@ export type NotificationProps = { color?: never; }; -export type CommonProps = { - /** - * Text representing advisory information related to the badge. Under the hood, this prop also serves as an accessible label for the component. - */ - title?: string; - /** - * Material Symbol name or SVG element used as the icon that will be placed next to the badge label in contextual mode. - */ - icon?: string | SVG; - /** - * Ref to be forwarded to the badge container element. - */ - ref?: React.Ref<HTMLDivElement>; - /** - * Size of the component. - */ - size?: "small" | "medium" | "large"; -}; - -type Props = (ContextualProps | NotificationProps) & CommonProps; - -export default Props; +export type BadgeProps = PrettifyTypes<ContextualBadgeProps> | PrettifyTypes<NotificationBadgeProps>; diff --git a/packages/lib/src/base-menu/types.ts b/packages/lib/src/base-menu/types.ts index e86c87e0ed..139cd4d7e1 100644 --- a/packages/lib/src/base-menu/types.ts +++ b/packages/lib/src/base-menu/types.ts @@ -1,5 +1,5 @@ import { ButtonHTMLAttributes, Dispatch, ReactElement, ReactNode, SetStateAction } from "react"; -import { SVG } from "../common/utils"; +import { SVG } from "../common/types"; type CommonItemProps = { badge?: ReactElement; diff --git a/packages/lib/src/breadcrumbs/Breadcrumbs.tsx b/packages/lib/src/breadcrumbs/Breadcrumbs.tsx index 774df0240a..d1ba3c12e7 100644 --- a/packages/lib/src/breadcrumbs/Breadcrumbs.tsx +++ b/packages/lib/src/breadcrumbs/Breadcrumbs.tsx @@ -1,6 +1,6 @@ import { useCallback } from "react"; import styled from "@emotion/styled"; -import BreadcrumbsProps from "./types"; +import { BreadcrumbsProps } from "./types"; import DxcDropdown from "../dropdown/Dropdown"; import DxcIcon from "../icon/Icon"; import Item from "./Item"; diff --git a/packages/lib/src/breadcrumbs/Item.tsx b/packages/lib/src/breadcrumbs/Item.tsx index 59b7707e02..b0f8836fdc 100644 --- a/packages/lib/src/breadcrumbs/Item.tsx +++ b/packages/lib/src/breadcrumbs/Item.tsx @@ -1,8 +1,8 @@ import { useRef, MouseEvent } from "react"; import styled from "@emotion/styled"; -import { ItemPropsType } from "./types"; +import { BreadcrumbsItemProps } from "./types"; -const ListItem = styled.li<{ isCurrentPage?: ItemPropsType["isCurrentPage"] }>` +const ListItem = styled.li<{ isCurrentPage?: BreadcrumbsItemProps["isCurrentPage"] }>` display: flex; align-items: center; color: var(--color-fg-neutral-dark); @@ -44,7 +44,7 @@ const Text = styled.span` } `; -const Item = ({ isCurrentPage = false, href, label, onClick }: ItemPropsType) => { +const Item = ({ isCurrentPage = false, href, label, onClick }: BreadcrumbsItemProps) => { const currentItemRef = useRef<HTMLSpanElement | null>(null); const handleOnClick = (event: MouseEvent<HTMLAnchorElement>) => { diff --git a/packages/lib/src/breadcrumbs/types.ts b/packages/lib/src/breadcrumbs/types.ts index 2912e649d9..a29f3934af 100644 --- a/packages/lib/src/breadcrumbs/types.ts +++ b/packages/lib/src/breadcrumbs/types.ts @@ -1,8 +1,10 @@ -type Item = { +import { PrettifyTypes } from "../common/types"; + +export type BreadcrumbsItem = { href?: string; label: string; }; -type Props = { +export type BreadcrumbsProps = { /** * Provides a label that describes the type of navigation enabled by * the component. @@ -11,7 +13,7 @@ type Props = { /** * Array of objects representing the items of the breadcrumbs. */ - items: Item[]; + items: BreadcrumbsItem[]; /** * Number of items before showing a collapsed version of the * breadcrumbs. It can't be lower than two (root/collapsed action and @@ -34,9 +36,9 @@ type Props = { showRoot?: boolean; }; -export type ItemPropsType = Item & { - isCurrentPage?: boolean; - onClick?: (href: string) => void; -}; - -export default Props; +export type BreadcrumbsItemProps = PrettifyTypes< + BreadcrumbsItem & { + isCurrentPage?: boolean; + onClick?: (href: string) => void; + } +>; diff --git a/packages/lib/src/bulleted-list/BulletedList.tsx b/packages/lib/src/bulleted-list/BulletedList.tsx index 5bae88571d..9ebfc89abe 100644 --- a/packages/lib/src/bulleted-list/BulletedList.tsx +++ b/packages/lib/src/bulleted-list/BulletedList.tsx @@ -2,7 +2,7 @@ import { JSX, Children } from "react"; import styled from "@emotion/styled"; import DxcFlex from "../flex/Flex"; import DxcTypography from "../typography/Typography"; -import BulletedListPropsType, { BulletedListItemPropsType } from "./types"; +import { BulletedListProps, BulletedListItemProps } from "./types"; import DxcIcon from "../icon/Icon"; const ListContainer = styled.div` @@ -79,9 +79,9 @@ const ListItem = styled.li` padding: var(--spacing-padding-none); `; -const BulletedListItem = ({ children }: BulletedListItemPropsType): JSX.Element => <>{children}</>; +const BulletedListItem = ({ children }: BulletedListItemProps): JSX.Element => <>{children}</>; -const DxcBulletedList = ({ children, type = "disc", icon = "" }: BulletedListPropsType): JSX.Element => ( +const DxcBulletedList = ({ children, type = "disc", icon = "" }: BulletedListProps): JSX.Element => ( <ListContainer> <DxcFlex direction="column" as={type === "number" ? "ol" : "ul"} gap="0.125rem"> {Children.map(children, (child, index) => ( diff --git a/packages/lib/src/bulleted-list/types.ts b/packages/lib/src/bulleted-list/types.ts index 24ae1f1125..ec955087bf 100644 --- a/packages/lib/src/bulleted-list/types.ts +++ b/packages/lib/src/bulleted-list/types.ts @@ -1,7 +1,7 @@ import { ReactNode } from "react"; -import { SVG } from "../common/utils"; +import { PrettifyTypes, SVG } from "../common/types"; -type IconProps = { +type BulletedListIconProps = { /** * Defines the style of the bullet point in the list. */ @@ -16,7 +16,7 @@ type IconProps = { children: ReactNode; }; -type OtherProps = { +type BulletedListWithoutIconProps = { /** * Defines the style of the bullet point in the list. */ @@ -31,13 +31,11 @@ type OtherProps = { children: ReactNode; }; -type Props = IconProps | OtherProps; +export type BulletedListProps = PrettifyTypes<BulletedListIconProps | BulletedListWithoutIconProps>; -export type BulletedListItemPropsType = { +export type BulletedListItemProps = { /** * Text to be shown in the list. */ children?: ReactNode; }; - -export default Props; diff --git a/packages/lib/src/button/Button.tsx b/packages/lib/src/button/Button.tsx index e7b9d09d8c..5784d59e22 100644 --- a/packages/lib/src/button/Button.tsx +++ b/packages/lib/src/button/Button.tsx @@ -1,17 +1,17 @@ import styled from "@emotion/styled"; import { spaces } from "../common/variables"; -import ButtonPropsType, { Mode, Semantic, Size } from "./types"; +import { ButtonMode, ButtonSemantic, ButtonSize, ButtonProps } from "./types"; import DxcIcon from "../icon/Icon"; import { Tooltip } from "../tooltip/Tooltip"; import { calculateWidth, getButtonStyles, getHeight } from "./utils"; const Button = styled.button<{ iconOnly: boolean; - iconPosition: ButtonPropsType["iconPosition"]; - margin: ButtonPropsType["margin"]; - semantic: Semantic; - size: Size; - $mode: Mode; + iconPosition: ButtonProps["iconPosition"]; + margin: ButtonProps["margin"]; + semantic: ButtonSemantic; + size: ButtonSize; + $mode: ButtonMode; }>` display: inline-flex; align-items: center; @@ -54,7 +54,7 @@ const LabelContainer = styled.span` `; const IconContainer = styled.div<{ - size: Size; + size: ButtonSize; }>` display: flex; font-size: ${({ size }) => @@ -80,7 +80,7 @@ const DxcButton = ({ tabIndex = 0, title, type = "button", -}: ButtonPropsType) => { +}: ButtonProps) => { return ( <Tooltip label={title}> <Button diff --git a/packages/lib/src/button/types.ts b/packages/lib/src/button/types.ts index 7f60a651fc..611b9aaea2 100644 --- a/packages/lib/src/button/types.ts +++ b/packages/lib/src/button/types.ts @@ -1,8 +1,8 @@ -import { Margin, SVG, Space } from "../common/utils"; +import { Margin, SVG, Space } from "../common/types"; -export type Semantic = "default" | "error" | "warning" | "success" | "info"; -export type Mode = "primary" | "secondary" | "tertiary"; -export type Size = { +export type ButtonSemantic = "default" | "error" | "warning" | "success" | "info"; +export type ButtonMode = "primary" | "secondary" | "tertiary"; +export type ButtonSize = { /** * Height of the button. */ @@ -13,7 +13,7 @@ export type Size = { width?: "small" | "medium" | "large" | "fillParent" | "fitContent"; }; -type Props = { +export type ButtonProps = { /** * If true, the component will be disabled. */ @@ -38,7 +38,7 @@ type Props = { /** * The available button modes. */ - mode?: Mode; + mode?: ButtonMode; /** * This function will be called when the user clicks the button. */ @@ -50,11 +50,11 @@ type Props = { /** * Specifies the semantic meaning of the buttons, which determines its color. */ - semantic?: Semantic; + semantic?: ButtonSemantic; /** * Size of the component. */ - size?: Size; + size?: ButtonSize; /** * Value of the tabindex attribute. */ @@ -68,5 +68,3 @@ type Props = { */ type?: "button" | "reset" | "submit"; }; - -export default Props; diff --git a/packages/lib/src/button/utils.ts b/packages/lib/src/button/utils.ts index 9bd0f81cbe..080a0ac532 100644 --- a/packages/lib/src/button/utils.ts +++ b/packages/lib/src/button/utils.ts @@ -1,7 +1,11 @@ import { getMargin } from "../common/utils"; -import ButtonPropsType, { Mode, Semantic, Size } from "./types"; +import { ButtonProps, ButtonMode, ButtonSemantic, ButtonSize } from "./types"; -export const getButtonStyles = (mode: Mode, semantic: Semantic | "unselected" | "selected", size: Size) => { +export const getButtonStyles = ( + mode: ButtonMode, + semantic: ButtonSemantic | "unselected" | "selected", + size: ButtonSize +) => { let enabled = ""; let hover = ""; let active = ""; @@ -207,12 +211,12 @@ const widths = { fitContent: "fit-content", }; -export const calculateWidth = (margin: ButtonPropsType["margin"], size: ButtonPropsType["size"]) => +export const calculateWidth = (margin: ButtonProps["margin"], size: ButtonProps["size"]) => size?.width === "fillParent" ? `calc(${widths[size?.width]} - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})` : size?.width && widths[size?.width]; -export const getHeight = (height: Size["height"]) => { +export const getHeight = (height: ButtonSize["height"]) => { switch (height) { case "small": return "var(--height-s)"; diff --git a/packages/lib/src/checkbox/types.ts b/packages/lib/src/checkbox/types.ts index dbcaa461a0..2f96265bd0 100644 --- a/packages/lib/src/checkbox/types.ts +++ b/packages/lib/src/checkbox/types.ts @@ -1,4 +1,4 @@ -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; /** * Reference to the component. diff --git a/packages/lib/src/chip/types.ts b/packages/lib/src/chip/types.ts index 4cdf0c9a0b..e9f5205fb6 100644 --- a/packages/lib/src/chip/types.ts +++ b/packages/lib/src/chip/types.ts @@ -1,4 +1,4 @@ -import { SVG } from "../common/utils"; +import { SVG } from "../common/types"; import AvatarProps from "../avatar/types"; export type ChipAvatarType = { diff --git a/packages/lib/src/common/types.ts b/packages/lib/src/common/types.ts new file mode 100644 index 0000000000..4b56377f5b --- /dev/null +++ b/packages/lib/src/common/types.ts @@ -0,0 +1,22 @@ +import React from "react"; + +export type Space = "xxsmall" | "xsmall" | "small" | "medium" | "large" | "xlarge" | "xxlarge"; +export type Margin = { + top?: Space; + bottom?: Space; + left?: Space; + right?: Space; +}; +export type SVG = React.ReactNode & React.SVGProps<SVGSVGElement>; +export type Side = keyof Margin; + +export type Size = "xsmall" | "small" | "medium" | "large" | "xlarge" | "xxlarge"; +export type Shape = "circle" | "square"; +export type Color = "primary" | "secondary" | "tertiary" | "success" | "info" | "neutral" | "warning" | "error"; + +/** + * Utility type to make complex types more readable in TypeScript. + */ +export type PrettifyTypes<T> = { + [K in keyof T]: T[K]; +} & {}; diff --git a/packages/lib/src/common/utils.ts b/packages/lib/src/common/utils.ts index 13ececd8f1..04230e5c67 100644 --- a/packages/lib/src/common/utils.ts +++ b/packages/lib/src/common/utils.ts @@ -1,15 +1,5 @@ -import { ReactNode, SVGProps } from "react"; import { spaces } from "./variables"; - -export type Space = "xxsmall" | "xsmall" | "small" | "medium" | "large" | "xlarge" | "xxlarge"; -export type Margin = { - top?: Space; - bottom?: Space; - left?: Space; - right?: Space; -}; -export type SVG = ReactNode & SVGProps<SVGSVGElement>; -export type Side = keyof Margin; +import { Space, Margin, Side } from "./types"; export const getMargin = (marginProp: Space | Margin | undefined, side: Side) => marginProp && typeof marginProp === "object" diff --git a/packages/lib/src/container/Container.tsx b/packages/lib/src/container/Container.tsx index 52ff9cf1b1..0fb1103a41 100644 --- a/packages/lib/src/container/Container.tsx +++ b/packages/lib/src/container/Container.tsx @@ -1,5 +1,5 @@ import styled from "@emotion/styled"; -import ContainerPropsType, { BorderProperties, StyledProps } from "./types"; +import { BorderProperties, StyledProps, ContainerProps } from "./types"; const getBorderStyles = (direction: "top" | "bottom" | "left" | "right", borderProperties: BorderProperties) => `border-${direction}: ${borderProperties.width ?? ""} ${borderProperties.style ?? ""} ${ @@ -82,7 +82,7 @@ const Container = styled.div<StyledProps>` padding-left: ${({ padding }) => (typeof padding === "object" && padding.left ? padding.left : "")}; `; -const DxcContainer = ({ display, width, height, overflow, ref, ...props }: ContainerPropsType) => ( +const DxcContainer = ({ display, width, height, overflow, ref, ...props }: ContainerProps) => ( <Container ref={ref} $display={display} $width={width} $height={height} $overflow={overflow} {...props} /> ); diff --git a/packages/lib/src/container/types.ts b/packages/lib/src/container/types.ts index 36457c0450..ed2ce200b2 100644 --- a/packages/lib/src/container/types.ts +++ b/packages/lib/src/container/types.ts @@ -1,20 +1,13 @@ import { ReactNode, Ref } from "react"; -type Space = { +export type Spacing = { top?: string; right?: string; bottom?: string; left?: string; }; -type Inset = { - top?: string; - right?: string; - bottom?: string; - left?: string; -}; - -type Background = { +export type Background = { attachment?: string; clip?: string; color?: string; @@ -30,7 +23,7 @@ export type BorderProperties = { style?: string; color?: string; }; -type Border = +export type Border = | BorderProperties | { top?: BorderProperties; @@ -39,14 +32,14 @@ type Border = left?: BorderProperties; }; -type Outline = BorderProperties & { +export type Outline = BorderProperties & { offset?: string; }; -type OverflowValues = "visible" | "hidden" | "clip" | "scroll" | "auto"; -type Overflow = OverflowValues | { x?: OverflowValues; y?: OverflowValues }; +export type OverflowValues = "visible" | "hidden" | "clip" | "scroll" | "auto"; +export type Overflow = OverflowValues | { x?: OverflowValues; y?: OverflowValues }; -type Props = { +export type ContainerProps = { /** * Based on the CSS property background allows configuring all properties related to the background of a container. * @@ -108,11 +101,11 @@ type Props = { * Based on the CSS property inset this prop is a shorthand that corresponds * to the top, right, bottom, and/or left properties. */ - inset?: Inset; + inset?: Spacing; /** * Size of the margin to be applied to the container. */ - margin?: string | Space; + margin?: string | Spacing; /** * Sets the max-width CSS property. * @@ -151,7 +144,7 @@ type Props = { /** * Size of the padding to be applied to the container. */ - padding?: string | Space; + padding?: string | Spacing; /** * Sets the position CSS property. * @@ -172,11 +165,9 @@ type Props = { zIndex?: "auto" | number; }; -export type StyledProps = Omit<Props, "display" | "width" | "height" | "opacity" | "overflow"> & { +export type StyledProps = Omit<ContainerProps, "display" | "width" | "height" | "opacity" | "overflow"> & { $display?: "block" | "inline-block" | "inline" | "none"; $height?: string; $overflow?: Overflow; $width?: string; }; - -export default Props; diff --git a/packages/lib/src/date-input/types.ts b/packages/lib/src/date-input/types.ts index d34f89f94e..1f056cb6a2 100644 --- a/packages/lib/src/date-input/types.ts +++ b/packages/lib/src/date-input/types.ts @@ -1,5 +1,5 @@ import { Dayjs } from "dayjs"; -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; export type RefType = React.Ref<HTMLDivElement>; diff --git a/packages/lib/src/dropdown/types.ts b/packages/lib/src/dropdown/types.ts index 03d3bc44e9..8474892c13 100644 --- a/packages/lib/src/dropdown/types.ts +++ b/packages/lib/src/dropdown/types.ts @@ -1,5 +1,5 @@ import { CSSProperties, KeyboardEvent } from "react"; -import { Margin, SVG, Space } from "../common/utils"; +import { Margin, SVG, Space } from "../common/types"; type Size = "small" | "medium" | "large" | "fillParent" | "fitContent"; diff --git a/packages/lib/src/file-input/types.ts b/packages/lib/src/file-input/types.ts index 189b76e245..3bf58f28c9 100644 --- a/packages/lib/src/file-input/types.ts +++ b/packages/lib/src/file-input/types.ts @@ -1,4 +1,4 @@ -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; /** * Reference to the component. diff --git a/packages/lib/src/footer/types.ts b/packages/lib/src/footer/types.ts index 99aa3a3cd9..37f74aa978 100644 --- a/packages/lib/src/footer/types.ts +++ b/packages/lib/src/footer/types.ts @@ -1,5 +1,5 @@ import { ReactNode } from "react"; -import { SVG } from "../common/utils"; +import { SVG } from "../common/types"; type SocialLink = { /** diff --git a/packages/lib/src/global.d.ts b/packages/lib/src/global.d.ts index 645ab52174..5a60fc8359 100644 --- a/packages/lib/src/global.d.ts +++ b/packages/lib/src/global.d.ts @@ -7,3 +7,5 @@ declare module "*.woff" { const content: string; export default content; } + +declare module "*.css" {} diff --git a/packages/lib/src/heading/types.ts b/packages/lib/src/heading/types.ts index 0b37579636..5a12a363c4 100644 --- a/packages/lib/src/heading/types.ts +++ b/packages/lib/src/heading/types.ts @@ -1,4 +1,4 @@ -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; type Props = { /** diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index e776fe13c3..b2edbb2dcc 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -55,3 +55,29 @@ export { default as DxcTypography } from "./typography/Typography"; export { default as DxcWizard } from "./wizard/Wizard"; export { HalstackProvider, HalstackLanguageContext } from "./HalstackContext"; export { default as useToast } from "./toast/useToast"; + +export type { + AccordionProps as DxcAccordionProps, + AccordionItemProps as DxcAccordionItemProps, +} from "./accordion/types"; +export type { + AlertProps as DxcAlertProps, + AlertAction as DxcAlertAction, + AlertMessage as DxcAlertMessage, +} from "./alert/types"; +export type { AvatarProps as DxcAvatarProps, AvatarStatus as DxcAvatarStatus } from "./avatar/types"; +export type { BadgeProps as DxcBadgeProps } from "./badge/types"; +export type { + BreadcrumbsProps as DxcBreadcrumbsProps, + BreadcrumbsItemProps as DxcBreadcrumbsItemProps, +} from "./breadcrumbs/types"; +export type { + BulletedListProps as DxcBulletedListProps, + BulletedListItemProps as DxcBulletedListItemProps, +} from "./bulleted-list/types"; +export type { + ButtonProps as DxcButtonPropsType, + ButtonMode as DxcButtonMode, + ButtonSemantic as DxcButtonSemantic, + ButtonSize as DxcButtonSize, +} from "./button/types"; diff --git a/packages/lib/src/layout/types.ts b/packages/lib/src/layout/types.ts index f8b1e667ac..23da6ce3ab 100644 --- a/packages/lib/src/layout/types.ts +++ b/packages/lib/src/layout/types.ts @@ -1,5 +1,5 @@ import { ReactElement, ReactNode } from "react"; -import { SVG } from "../common/utils"; +import { SVG } from "../common/types"; export type AppLayoutMainPropsType = { /** diff --git a/packages/lib/src/link/types.ts b/packages/lib/src/link/types.ts index 08c3b0e13c..6e2442518e 100644 --- a/packages/lib/src/link/types.ts +++ b/packages/lib/src/link/types.ts @@ -1,4 +1,4 @@ -import { Margin, SVG, Space } from "../common/utils"; +import { Margin, SVG, Space } from "../common/types"; export type LinkProps = { /** diff --git a/packages/lib/src/nav-tabs/types.ts b/packages/lib/src/nav-tabs/types.ts index 583624fa46..53a8a7a780 100644 --- a/packages/lib/src/nav-tabs/types.ts +++ b/packages/lib/src/nav-tabs/types.ts @@ -1,5 +1,5 @@ import { ReactNode } from "react"; -import { SVG } from "../common/utils"; +import { SVG } from "../common/types"; export type NavTabsContextProps = { focusedLabel: string | undefined; diff --git a/packages/lib/src/number-input/types.ts b/packages/lib/src/number-input/types.ts index 916aba19cd..9bf33e5889 100644 --- a/packages/lib/src/number-input/types.ts +++ b/packages/lib/src/number-input/types.ts @@ -1,4 +1,4 @@ -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; /** * Reference to the component. diff --git a/packages/lib/src/password-input/types.ts b/packages/lib/src/password-input/types.ts index 910fb44c06..b9257995dd 100644 --- a/packages/lib/src/password-input/types.ts +++ b/packages/lib/src/password-input/types.ts @@ -1,4 +1,4 @@ -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; /** * Reference to the component. diff --git a/packages/lib/src/progress-bar/types.ts b/packages/lib/src/progress-bar/types.ts index daa4a988d2..c73cb0e8c0 100644 --- a/packages/lib/src/progress-bar/types.ts +++ b/packages/lib/src/progress-bar/types.ts @@ -1,11 +1,4 @@ -import { Space } from "../common/utils"; - -type Size = { - top?: Space; - bottom?: Space; - left?: Space; - right?: Space; -}; +import { Margin, Space } from "../common/types"; type Props = { /** @@ -34,7 +27,7 @@ type Props = { * an object with 'top', 'bottom', 'left' and 'right' properties * in order to specify different margin sizes. */ - margin?: Space | Size; + margin?: Space | Margin; /** * Specifies a string to be used as the name for the progress bar element when no `label` is provided. */ diff --git a/packages/lib/src/resultset-table/types.ts b/packages/lib/src/resultset-table/types.ts index 766092b967..0f02252b97 100644 --- a/packages/lib/src/resultset-table/types.ts +++ b/packages/lib/src/resultset-table/types.ts @@ -1,5 +1,5 @@ import { ReactNode } from "react"; -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; export type Column = { /** diff --git a/packages/lib/src/select/types.ts b/packages/lib/src/select/types.ts index ae2759a700..3157898de0 100644 --- a/packages/lib/src/select/types.ts +++ b/packages/lib/src/select/types.ts @@ -1,5 +1,5 @@ import { CSSProperties } from "react"; -import { Margin, SVG, Space } from "../common/utils"; +import { Margin, SVG, Space } from "../common/types"; /** * Reference to the select component. diff --git a/packages/lib/src/slider/types.ts b/packages/lib/src/slider/types.ts index 16f93d42d2..5cd03af39d 100644 --- a/packages/lib/src/slider/types.ts +++ b/packages/lib/src/slider/types.ts @@ -1,4 +1,4 @@ -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; /** * Reference to the component. diff --git a/packages/lib/src/spinner/types.ts b/packages/lib/src/spinner/types.ts index 129d70d81c..37f66f8aa8 100644 --- a/packages/lib/src/spinner/types.ts +++ b/packages/lib/src/spinner/types.ts @@ -1,4 +1,4 @@ -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; type Props = { /** diff --git a/packages/lib/src/switch/types.ts b/packages/lib/src/switch/types.ts index a731e8853d..babff51519 100644 --- a/packages/lib/src/switch/types.ts +++ b/packages/lib/src/switch/types.ts @@ -1,4 +1,4 @@ -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; /** * Reference to the component. diff --git a/packages/lib/src/table/types.ts b/packages/lib/src/table/types.ts index 4152ab4963..af2a478784 100644 --- a/packages/lib/src/table/types.ts +++ b/packages/lib/src/table/types.ts @@ -1,5 +1,5 @@ import { ReactNode } from "react"; -import { Margin, SVG, Space } from "../common/utils"; +import { Margin, SVG, Space } from "../common/types"; import { Option } from "../dropdown/types"; type BaseActionCell = { diff --git a/packages/lib/src/tabs/types.ts b/packages/lib/src/tabs/types.ts index 9322e5844a..ba6fd7decc 100644 --- a/packages/lib/src/tabs/types.ts +++ b/packages/lib/src/tabs/types.ts @@ -1,6 +1,6 @@ import { ReactNode } from "react"; -import type { Space, Margin, SVG } from "../common/utils"; +import type { Space, Margin, SVG } from "../common/types"; export type TabsContextProps = { activeTabId?: string; diff --git a/packages/lib/src/text-input/types.ts b/packages/lib/src/text-input/types.ts index 0670261b6f..e83a29a0c7 100644 --- a/packages/lib/src/text-input/types.ts +++ b/packages/lib/src/text-input/types.ts @@ -1,5 +1,5 @@ import { JSX, CSSProperties, ReactNode } from "react"; -import { Margin, SVG, Space } from "../common/utils"; +import { Margin, SVG, Space } from "../common/types"; type Action = { /** diff --git a/packages/lib/src/textarea/types.ts b/packages/lib/src/textarea/types.ts index db5d747c34..102fe716d5 100644 --- a/packages/lib/src/textarea/types.ts +++ b/packages/lib/src/textarea/types.ts @@ -1,4 +1,4 @@ -import { Margin, Space } from "../common/utils"; +import { Margin, Space } from "../common/types"; /** * Reference to the component. diff --git a/packages/lib/src/toast/types.ts b/packages/lib/src/toast/types.ts index c38c156070..5fdb7363db 100644 --- a/packages/lib/src/toast/types.ts +++ b/packages/lib/src/toast/types.ts @@ -1,5 +1,5 @@ import { ReactNode } from "react"; -import { SVG } from "../common/utils"; +import { SVG } from "../common/types"; type Action = { /** diff --git a/packages/lib/src/toggle-group/types.ts b/packages/lib/src/toggle-group/types.ts index fe055c35f4..f8ddf92056 100644 --- a/packages/lib/src/toggle-group/types.ts +++ b/packages/lib/src/toggle-group/types.ts @@ -1,4 +1,4 @@ -import { Margin, SVG, Space } from "../common/utils"; +import { Margin, SVG, Space } from "../common/types"; type OptionIcon = { /** diff --git a/packages/lib/src/wizard/types.ts b/packages/lib/src/wizard/types.ts index 074edb1d3e..97621ea1f2 100644 --- a/packages/lib/src/wizard/types.ts +++ b/packages/lib/src/wizard/types.ts @@ -1,4 +1,4 @@ -import { Margin, SVG, Space } from "../common/utils"; +import { Margin, SVG, Space } from "../common/types"; export type StepProps = { /** From 5a290e9f1a6b21fe23e9577bc9f90f33125e9b35 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Wed, 14 Oct 2026 09:43:20 +0200 Subject: [PATCH 02/18] Adding default exports --- packages/lib/src/accordion/types.ts | 2 + .../src/action-icon/ActionIcon.stories.tsx | 6 +- packages/lib/src/action-icon/types.ts | 2 + packages/lib/src/alert/types.ts | 58 ++++++++++--------- packages/lib/src/avatar/types.ts | 2 + packages/lib/src/badge/types.ts | 2 + packages/lib/src/bleed/Bleed.tsx | 4 +- packages/lib/src/bleed/types.ts | 4 +- packages/lib/src/breadcrumbs/types.ts | 2 + packages/lib/src/bulleted-list/types.ts | 2 + packages/lib/src/button/types.ts | 2 + packages/lib/src/chip/Chip.tsx | 2 +- packages/lib/src/index.ts | 27 ++++----- 13 files changed, 67 insertions(+), 48 deletions(-) diff --git a/packages/lib/src/accordion/types.ts b/packages/lib/src/accordion/types.ts index 2d6afdf098..0277ac928f 100644 --- a/packages/lib/src/accordion/types.ts +++ b/packages/lib/src/accordion/types.ts @@ -111,3 +111,5 @@ export type AccordionContextProps = { handlerActiveChange?: (index: number | number[]) => void; independent?: boolean; }; + +export type { AccordionProps as default }; \ No newline at end of file diff --git a/packages/lib/src/action-icon/ActionIcon.stories.tsx b/packages/lib/src/action-icon/ActionIcon.stories.tsx index e49938ec8e..8bfb6f5555 100644 --- a/packages/lib/src/action-icon/ActionIcon.stories.tsx +++ b/packages/lib/src/action-icon/ActionIcon.stories.tsx @@ -30,7 +30,7 @@ type ActionIconRowProps = { const ActionIconRow = ({ sizes = ["medium"], shapes = ["circle"], - colors = ["neutral"], + colors = [undefined], statusModes, statusPositions = [], pseudoStates = [], @@ -144,6 +144,7 @@ export const Shapes: Story = { sizes={["xsmall", "small", "medium", "large", "xlarge", "xxlarge"]} shapes={["circle", "square"]} groupBy={["shape", "size"]} + colors={["neutral"]} /> </> ), @@ -156,9 +157,10 @@ export const Colors: Story = { <ActionIconRow sizes={["medium"]} shapes={["circle"]} - colors={["neutral", "primary", "secondary", "tertiary", "success", "warning", "error", "info", undefined]} + colors={["neutral", "primary", "secondary", "tertiary", "success", "warning", "error", "info"]} groupBy={["color"]} /> + <ActionIconRow colors={undefined} sizes={["medium"]} shapes={["circle"]} groupBy={["color"]} /> </> ), }; diff --git a/packages/lib/src/action-icon/types.ts b/packages/lib/src/action-icon/types.ts index 61786e2ce0..9430e25b51 100644 --- a/packages/lib/src/action-icon/types.ts +++ b/packages/lib/src/action-icon/types.ts @@ -53,3 +53,5 @@ type CommonProps = { export type ActionIconProps = | (CommonProps & { content: ReactNode; icon?: string | SVG }) | (CommonProps & { content?: ReactNode; icon: string | SVG }); + +export type { ActionIconProps as default }; \ No newline at end of file diff --git a/packages/lib/src/alert/types.ts b/packages/lib/src/alert/types.ts index a4adce5f12..581898af17 100644 --- a/packages/lib/src/alert/types.ts +++ b/packages/lib/src/alert/types.ts @@ -56,35 +56,35 @@ type CommonProps = { type ModeSpecificProps = | { - /** - * List of messages to be displayed. Each message has a close action that will, - * apart from remove from the alert the current message, call the onClose if it is defined. - * If the message is an array, the alert will show a navigation bar to move between the messages. - * The modal mode only allows one message per alert. In this case, the message must be an object - * and the presence of the onClose attribute is mandatory, since the management of the closing - * of the alert relies completely on the user. - */ - message?: AlertMessage | AlertMessage[]; - /** - * The mode of the alert. - */ - mode?: "inline" | "banner"; - } + /** + * List of messages to be displayed. Each message has a close action that will, + * apart from remove from the alert the current message, call the onClose if it is defined. + * If the message is an array, the alert will show a navigation bar to move between the messages. + * The modal mode only allows one message per alert. In this case, the message must be an object + * and the presence of the onClose attribute is mandatory, since the management of the closing + * of the alert relies completely on the user. + */ + message?: AlertMessage | AlertMessage[]; + /** + * The mode of the alert. + */ + mode?: "inline" | "banner"; + } | { - /** - * List of messages to be displayed. Each message has a close action that will, - * apart from remove from the alert the current message, call the onClose if it is defined. - * If the message is an array, the alert will show a navigation bar to move between the messages. - * The modal mode only allows one message per alert. In this case, the message must be an object - * and the presence of the onClose attribute is mandatory, since the management of the closing - * of the alert relies completely on the user. - */ - message: Required<AlertMessage>; - /** - * The mode of the alert. - */ - mode: "modal"; - }; + /** + * List of messages to be displayed. Each message has a close action that will, + * apart from remove from the alert the current message, call the onClose if it is defined. + * If the message is an array, the alert will show a navigation bar to move between the messages. + * The modal mode only allows one message per alert. In this case, the message must be an object + * and the presence of the onClose attribute is mandatory, since the management of the closing + * of the alert relies completely on the user. + */ + message: Required<AlertMessage>; + /** + * The mode of the alert. + */ + mode: "modal"; + }; export type AlertProps = PrettifyTypes<CommonProps & ModeSpecificProps>; @@ -93,3 +93,5 @@ export type ModalAlertWrapperProps = { onClose?: () => void; children: ReactNode; }; + +export type { AlertProps as default }; \ No newline at end of file diff --git a/packages/lib/src/avatar/types.ts b/packages/lib/src/avatar/types.ts index aaef6afb41..1c7d9692d2 100644 --- a/packages/lib/src/avatar/types.ts +++ b/packages/lib/src/avatar/types.ts @@ -94,3 +94,5 @@ export type ContentType = { color: Color; status?: AvatarStatus; }; + +export type { AvatarProps as default }; \ No newline at end of file diff --git a/packages/lib/src/badge/types.ts b/packages/lib/src/badge/types.ts index b1be76d723..2370b66828 100644 --- a/packages/lib/src/badge/types.ts +++ b/packages/lib/src/badge/types.ts @@ -58,3 +58,5 @@ export type NotificationBadgeProps = CommonProps & { }; export type BadgeProps = PrettifyTypes<ContextualBadgeProps> | PrettifyTypes<NotificationBadgeProps>; + +export type { BadgeProps as default }; \ No newline at end of file diff --git a/packages/lib/src/bleed/Bleed.tsx b/packages/lib/src/bleed/Bleed.tsx index c4a9af9f6d..2f40334875 100644 --- a/packages/lib/src/bleed/Bleed.tsx +++ b/packages/lib/src/bleed/Bleed.tsx @@ -1,9 +1,9 @@ -import BleedPropsType from "./types"; +import { BleedProps } from "./types"; import DxcContainer from "../container/Container"; const getNegativeValue = (value?: string) => (value ? `calc(${value} * -1)` : null); -const DxcBleed = ({ space, horizontal, vertical, top, right, bottom, left, children }: BleedPropsType) => ( +const DxcBleed = ({ space, horizontal, vertical, top, right, bottom, left, children }: BleedProps) => ( <DxcContainer margin={{ top: getNegativeValue(top) ?? getNegativeValue(vertical) ?? getNegativeValue(space) ?? "0rem", diff --git a/packages/lib/src/bleed/types.ts b/packages/lib/src/bleed/types.ts index c008340530..19652b5a0a 100644 --- a/packages/lib/src/bleed/types.ts +++ b/packages/lib/src/bleed/types.ts @@ -1,6 +1,6 @@ import { ReactNode } from "react"; -type Props = { +export type BleedProps = { /** * Applies the spacing scale to all sides. */ @@ -35,4 +35,4 @@ type Props = { children: ReactNode; }; -export default Props; +export type { BleedProps as default }; diff --git a/packages/lib/src/breadcrumbs/types.ts b/packages/lib/src/breadcrumbs/types.ts index a29f3934af..195857b5e2 100644 --- a/packages/lib/src/breadcrumbs/types.ts +++ b/packages/lib/src/breadcrumbs/types.ts @@ -42,3 +42,5 @@ export type BreadcrumbsItemProps = PrettifyTypes< onClick?: (href: string) => void; } >; + +export type { BreadcrumbsProps as default }; \ No newline at end of file diff --git a/packages/lib/src/bulleted-list/types.ts b/packages/lib/src/bulleted-list/types.ts index ec955087bf..2a4c8aee13 100644 --- a/packages/lib/src/bulleted-list/types.ts +++ b/packages/lib/src/bulleted-list/types.ts @@ -39,3 +39,5 @@ export type BulletedListItemProps = { */ children?: ReactNode; }; + +export type { BulletedListProps as default }; \ No newline at end of file diff --git a/packages/lib/src/button/types.ts b/packages/lib/src/button/types.ts index 611b9aaea2..0167cfe64f 100644 --- a/packages/lib/src/button/types.ts +++ b/packages/lib/src/button/types.ts @@ -68,3 +68,5 @@ export type ButtonProps = { */ type?: "button" | "reset" | "submit"; }; + +export type { ButtonProps as default }; diff --git a/packages/lib/src/chip/Chip.tsx b/packages/lib/src/chip/Chip.tsx index ded48e62f8..3af103f57f 100644 --- a/packages/lib/src/chip/Chip.tsx +++ b/packages/lib/src/chip/Chip.tsx @@ -4,7 +4,7 @@ import ChipPropsType, { ChipAvatarType } from "./types"; import DxcActionIcon from "../action-icon/ActionIcon"; import DxcAvatar from "../avatar/Avatar"; import { isValidElement, ReactNode, useState } from "react"; -import { SVG } from "../common/utils"; +import { SVG } from "../common/types"; import { getChipStyles } from "./utils"; const Chip = styled.div<{ diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index b2edbb2dcc..3e845a4965 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -56,28 +56,29 @@ export { default as DxcWizard } from "./wizard/Wizard"; export { HalstackProvider, HalstackLanguageContext } from "./HalstackContext"; export { default as useToast } from "./toast/useToast"; +// types exports export type { - AccordionProps as DxcAccordionProps, - AccordionItemProps as DxcAccordionItemProps, + AccordionProps as DxcAccordionProps, + AccordionItemProps as DxcAccordionItemProps, } from "./accordion/types"; export type { - AlertProps as DxcAlertProps, - AlertAction as DxcAlertAction, - AlertMessage as DxcAlertMessage, + AlertProps as DxcAlertProps, + AlertAction as DxcAlertAction, + AlertMessage as DxcAlertMessage, } from "./alert/types"; export type { AvatarProps as DxcAvatarProps, AvatarStatus as DxcAvatarStatus } from "./avatar/types"; export type { BadgeProps as DxcBadgeProps } from "./badge/types"; export type { - BreadcrumbsProps as DxcBreadcrumbsProps, - BreadcrumbsItemProps as DxcBreadcrumbsItemProps, + BreadcrumbsProps as DxcBreadcrumbsProps, + BreadcrumbsItemProps as DxcBreadcrumbsItemProps, } from "./breadcrumbs/types"; export type { - BulletedListProps as DxcBulletedListProps, - BulletedListItemProps as DxcBulletedListItemProps, + BulletedListProps as DxcBulletedListProps, + BulletedListItemProps as DxcBulletedListItemProps, } from "./bulleted-list/types"; export type { - ButtonProps as DxcButtonPropsType, - ButtonMode as DxcButtonMode, - ButtonSemantic as DxcButtonSemantic, - ButtonSize as DxcButtonSize, + ButtonProps as DxcButtonPropsType, + ButtonMode as DxcButtonMode, + ButtonSemantic as DxcButtonSemantic, + ButtonSize as DxcButtonSize, } from "./button/types"; From 5d5529c8d692765ad473aaa34a7ffae788ba8568 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Wed, 14 Oct 2026 09:53:27 +0200 Subject: [PATCH 03/18] Trying to remove visual changes in action icon --- packages/lib/src/action-icon/ActionIcon.stories.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/lib/src/action-icon/ActionIcon.stories.tsx b/packages/lib/src/action-icon/ActionIcon.stories.tsx index 8bfb6f5555..4f9f41f799 100644 --- a/packages/lib/src/action-icon/ActionIcon.stories.tsx +++ b/packages/lib/src/action-icon/ActionIcon.stories.tsx @@ -192,12 +192,14 @@ export const Types: Story = { sizes={["xsmall", "small", "medium", "large", "xlarge", "xxlarge"]} shapes={["circle"]} groupBy={["size"]} + colors={undefined} /> <Title title="Icon (default)" theme="light" level={2} /> <ActionIconRow sizes={["xsmall", "small", "medium", "large", "xlarge", "xxlarge"]} shapes={["circle"]} groupBy={["size"]} + colors={undefined} /> </> ), From d1aae9ba600c035b4e7baf77ae30eeacde61ebd0 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Wed, 14 Oct 2026 10:02:55 +0200 Subject: [PATCH 04/18] Visual test removed due to unnecessary --- .../src/action-icon/ActionIcon.stories.tsx | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/lib/src/action-icon/ActionIcon.stories.tsx b/packages/lib/src/action-icon/ActionIcon.stories.tsx index 4f9f41f799..b44b03b0f0 100644 --- a/packages/lib/src/action-icon/ActionIcon.stories.tsx +++ b/packages/lib/src/action-icon/ActionIcon.stories.tsx @@ -184,26 +184,26 @@ export const PseudoStates: Story = { ), }; -export const Types: Story = { - render: () => ( - <> - <Title title="Icon (custom)" theme="light" level={2} /> - <ActionIconRow - sizes={["xsmall", "small", "medium", "large", "xlarge", "xxlarge"]} - shapes={["circle"]} - groupBy={["size"]} - colors={undefined} - /> - <Title title="Icon (default)" theme="light" level={2} /> - <ActionIconRow - sizes={["xsmall", "small", "medium", "large", "xlarge", "xxlarge"]} - shapes={["circle"]} - groupBy={["size"]} - colors={undefined} - /> - </> - ), -}; +// export const Types: Story = { +// render: () => ( +// <> +// <Title title="Icon (custom)" theme="light" level={2} /> +// <ActionIconRow +// sizes={["xsmall", "small", "medium", "large", "xlarge", "xxlarge"]} +// shapes={["circle"]} +// groupBy={["size"]} +// colors={["neutral"]} +// /> +// <Title title="Icon (default)" theme="light" level={2} /> +// <ActionIconRow +// sizes={["xsmall", "small", "medium", "large", "xlarge", "xxlarge"]} +// shapes={["circle"]} +// groupBy={["size"]} +// colors={["neutral"]} +// /> +// </> +// ), +// }; const Tooltip = () => ( <> From 71e4e82a05f4e9a1a587eca722776a17769b3c73 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Wed, 14 Oct 2026 10:35:27 +0200 Subject: [PATCH 05/18] Exporting types up to the Chip --- packages/lib/src/card/Card.tsx | 18 ++-- packages/lib/src/card/types.ts | 4 +- packages/lib/src/card/utils.ts | 12 +-- packages/lib/src/checkbox/Checkbox.tsx | 20 ++-- packages/lib/src/checkbox/types.ts | 4 +- packages/lib/src/chip/Chip.tsx | 12 +-- packages/lib/src/chip/types.ts | 128 +++++++++++++------------ packages/lib/src/container/types.ts | 18 ++-- packages/lib/src/index.ts | 30 +++--- 9 files changed, 130 insertions(+), 116 deletions(-) diff --git a/packages/lib/src/card/Card.tsx b/packages/lib/src/card/Card.tsx index 2653f30c6f..eec25a033b 100644 --- a/packages/lib/src/card/Card.tsx +++ b/packages/lib/src/card/Card.tsx @@ -1,6 +1,6 @@ import { Ref, use, useEffect, useState } from "react"; import styled from "@emotion/styled"; -import CardPropsType from "./types"; +import { CardProps } from "./types"; import DxcImage from "../image/Image"; import { getCardStyles, emptyIconSizes, handleEvent, getSelectableWrapperStyles } from "./utils"; import DxcFlex from "../flex/Flex"; @@ -9,13 +9,13 @@ import DxcTypography from "../typography/Typography"; import { HalstackLanguageContext } from "../HalstackContext"; const Card = styled.div<{ - mode: CardPropsType["mode"]; - direction?: CardPropsType["direction"]; - imagePosition?: CardPropsType["imagePosition"]; + mode: CardProps["mode"]; + direction?: CardProps["direction"]; + imagePosition?: CardProps["imagePosition"]; selectable?: boolean; interactive?: boolean; selected?: boolean; - size?: CardPropsType["size"]; + size?: CardProps["size"]; }>` display: flex; flex-direction: ${({ direction, imagePosition }) => @@ -38,7 +38,7 @@ const SelectableWrapper = styled.div<{ selected: boolean }>` overflow: hidden; `; -const EmptyCard = styled(Card)<{ emptySize?: CardPropsType["emptySize"] }>` +const EmptyCard = styled(Card)<{ emptySize?: CardProps["emptySize"] }>` display: flex; align-items: center; justify-content: center; @@ -47,7 +47,7 @@ const EmptyCard = styled(Card)<{ emptySize?: CardPropsType["emptySize"] }>` background: var(--color-bg-neutral-lighter); `; -const LoadingCard = styled(Card)<{ loadingSize?: CardPropsType["loadingSize"] }>` +const LoadingCard = styled(Card)<{ loadingSize?: CardProps["loadingSize"] }>` display: flex; align-items: center; justify-content: center; @@ -60,7 +60,7 @@ const CardLink = styled(Card.withComponent("a"))` text-decoration: none; `; -const ImageContainer = styled.div<{ image: CardPropsType["image"]; isLoading?: CardPropsType["isLoading"] }>` +const ImageContainer = styled.div<{ image: CardProps["image"]; isLoading?: CardProps["isLoading"] }>` display: flex; align-items: center; justify-content: center; @@ -114,7 +114,7 @@ const DxcCard = ({ selected, size = { width: "fitContent", height: "fitContent" }, tabIndex = 0, -}: CardPropsType) => { +}: CardProps) => { const isInteractive = !!(onClick || onSelectionChange) || selectable; const [internalSelected, setInternalSelected] = useState( selected !== undefined ? selected : defaultSelected || false diff --git a/packages/lib/src/card/types.ts b/packages/lib/src/card/types.ts index 4766177dda..21977162c0 100644 --- a/packages/lib/src/card/types.ts +++ b/packages/lib/src/card/types.ts @@ -6,7 +6,7 @@ type Size = { height?: "fillParent" | "fitContent"; }; -type Props = { +export type CardProps = { /** * Custom content that will be placed inside the component. */ @@ -98,4 +98,4 @@ type Props = { tabIndex?: number; }; -export default Props; +export type { CardProps as default }; diff --git a/packages/lib/src/card/utils.ts b/packages/lib/src/card/utils.ts index 20c84aa68f..868c3f1a58 100644 --- a/packages/lib/src/card/utils.ts +++ b/packages/lib/src/card/utils.ts @@ -1,14 +1,14 @@ -import CardPropsType from "./types"; +import { CardProps } from "./types"; -const calculateSize = (size?: CardPropsType["size"]) => { +const calculateSize = (size?: CardProps["size"]) => { return `width: ${size?.width === "fillParent" ? "100%" : "fit-content"}; height: ${size?.height === "fillParent" ? "100%" : "fit-content"};`; }; export const getCardStyles = ( - mode: CardPropsType["mode"], + mode: CardProps["mode"], interactive: boolean, selected?: boolean, - size?: CardPropsType["size"] + size?: CardProps["size"] ) => { let hover = ""; let focus = ""; @@ -81,8 +81,8 @@ export const getSelectableWrapperStyles = (selected: boolean) => { export const handleEvent = ( event: React.KeyboardEvent | React.MouseEvent, - onClick?: CardPropsType["onClick"], - onSelectionChange?: CardPropsType["onSelectionChange"], + onClick?: CardProps["onClick"], + onSelectionChange?: CardProps["onSelectionChange"], internalSelected?: boolean, setInternalSelected?: React.Dispatch<React.SetStateAction<boolean>>, selected?: boolean, diff --git a/packages/lib/src/checkbox/Checkbox.tsx b/packages/lib/src/checkbox/Checkbox.tsx index 4a0cfc3f50..5031b964aa 100644 --- a/packages/lib/src/checkbox/Checkbox.tsx +++ b/packages/lib/src/checkbox/Checkbox.tsx @@ -1,12 +1,12 @@ import { use, useState, useRef, useId, KeyboardEvent } from "react"; import styled from "@emotion/styled"; import { HalstackLanguageContext } from "../HalstackContext"; -import CheckboxPropsType from "./types"; +import { CheckboxProps } from "./types"; import { calculateWidth, icons, spaces } from "./utils"; import CheckboxContext from "./CheckboxContext"; const Label = styled.span<{ - disabled: CheckboxPropsType["disabled"]; + disabled: CheckboxProps["disabled"]; }>` color: ${({ disabled }) => (disabled ? "var(--color-fg-neutral-medium)" : "var(--color-fg-neutral-dark)")}; font-family: var(--typography-font-family); @@ -18,8 +18,8 @@ const Label = styled.span<{ `; const Checkbox = styled.span<{ - disabled: CheckboxPropsType["disabled"]; - readOnly: CheckboxPropsType["readOnly"]; + disabled: CheckboxProps["disabled"]; + readOnly: CheckboxProps["readOnly"]; }>` display: flex; border-radius: var(--border-radius-s); @@ -38,11 +38,11 @@ const Checkbox = styled.span<{ `; const CheckboxContainer = styled.div<{ - disabled: CheckboxPropsType["disabled"]; - labelPosition: CheckboxPropsType["labelPosition"]; - margin: CheckboxPropsType["margin"]; - readOnly: CheckboxPropsType["readOnly"]; - size: CheckboxPropsType["size"]; + disabled: CheckboxProps["disabled"]; + labelPosition: CheckboxProps["labelPosition"]; + margin: CheckboxProps["margin"]; + readOnly: CheckboxProps["readOnly"]; + size: CheckboxProps["size"]; }>` display: flex; align-items: center; @@ -86,7 +86,7 @@ const DxcCheckbox = ({ size = "fitContent", tabIndex = 0, value, -}: CheckboxPropsType) => { +}: CheckboxProps) => { const labelId = `label-checkbox-${useId()}`; const [innerChecked, setInnerChecked] = useState(defaultChecked); const checkboxRef = useRef<HTMLSpanElement | null>(null); diff --git a/packages/lib/src/checkbox/types.ts b/packages/lib/src/checkbox/types.ts index 2f96265bd0..fb3f1808aa 100644 --- a/packages/lib/src/checkbox/types.ts +++ b/packages/lib/src/checkbox/types.ts @@ -5,7 +5,7 @@ import { Margin, Space } from "../common/types"; */ export type RefType = HTMLDivElement; -type Props = { +export type CheckboxProps = { /** * Specifies a string to be used as the name for the checkbox element when no `label` is provided. */ @@ -78,4 +78,4 @@ export type CheckboxContextProps = { partial: boolean; }; -export default Props; +export type { CheckboxProps as default }; diff --git a/packages/lib/src/chip/Chip.tsx b/packages/lib/src/chip/Chip.tsx index 3af103f57f..27684c1198 100644 --- a/packages/lib/src/chip/Chip.tsx +++ b/packages/lib/src/chip/Chip.tsx @@ -1,6 +1,6 @@ import styled from "@emotion/styled"; import DxcIcon from "../icon/Icon"; -import ChipPropsType, { ChipAvatarType } from "./types"; +import { ChipProps, ChipAvatarType } from "./types"; import DxcActionIcon from "../action-icon/ActionIcon"; import DxcAvatar from "../avatar/Avatar"; import { isValidElement, ReactNode, useState } from "react"; @@ -8,9 +8,9 @@ import { SVG } from "../common/types"; import { getChipStyles } from "./utils"; const Chip = styled.div<{ - disabled: ChipPropsType["disabled"]; - mode: ChipPropsType["mode"]; - selected: ChipPropsType["selected"]; + disabled: ChipProps["disabled"]; + mode: ChipProps["mode"]; + selected: ChipProps["selected"]; isAvatar?: boolean; type?: string; }>` @@ -32,7 +32,7 @@ const Chip = styled.div<{ ${({ mode, selected }) => getChipStyles(mode, selected)} `; -const ContentWrapper = styled.div<{ mode: ChipPropsType["mode"] }>` +const ContentWrapper = styled.div<{ mode: ChipProps["mode"] }>` max-width: ${({ mode }) => (mode === "dismissible" ? "calc(100% - var(--spacing-gap-xxs) - 24px)" : "100%")}; display: inline-flex; align-items: center; @@ -96,7 +96,7 @@ const DxcChip = ({ selected, tabIndex = 0, ref, -}: ChipPropsType) => { +}: ChipProps) => { const [innerSelected, setInnerSelected] = useState(false); if (mode === "selectable" && isAvatarType(prefix) && !label) { diff --git a/packages/lib/src/chip/types.ts b/packages/lib/src/chip/types.ts index e9f5205fb6..e70ade4de2 100644 --- a/packages/lib/src/chip/types.ts +++ b/packages/lib/src/chip/types.ts @@ -1,4 +1,4 @@ -import { SVG } from "../common/types"; +import { PrettifyTypes, SVG } from "../common/types"; import AvatarProps from "../avatar/types"; export type ChipAvatarType = { @@ -23,67 +23,71 @@ type CommonProps = { tabIndex?: number; }; -type SelectableChipProps = CommonProps & { - /** - * If true, the component will be disabled. - */ - disabled?: boolean; - /** - * The whole chip is an interactive element that allows users to activate or clear options directly within the interface. - */ - mode?: "selectable"; - /** - * If true, the component will be selected. This property is only applicable when the mode is "selectable". - * If undefined, the component manages its own internal state (uncontrolled mode). - */ - selected?: boolean; -} & ( - | { - /** - * Element, path or avatar used as icon to be placed before the chip label. - */ - prefix: ChipAvatarType; - /** - * Text to be placed on the chip. Required when using an avatar prefix. - */ - label: string; - } - | { - /** - * Element or path used as icon to be placed before the chip label. - */ - prefix: string | SVG; - /** - * Text to be placed on the chip. Optional when using an icon prefix. - */ - label?: string; - } - | { - prefix?: undefined; - /** - * Text to be placed on the chip. - */ - label: string; - } - ); +type SelectableChipProps = PrettifyTypes< + CommonProps & { + /** + * If true, the component will be disabled. + */ + disabled?: boolean; + /** + * The whole chip is an interactive element that allows users to activate or clear options directly within the interface. + */ + mode?: "selectable"; + /** + * If true, the component will be selected. This property is only applicable when the mode is "selectable". + * If undefined, the component manages its own internal state (uncontrolled mode). + */ + selected?: boolean; + } & ( + | { + /** + * Element, path or avatar used as icon to be placed before the chip label. + */ + prefix: ChipAvatarType; + /** + * Text to be placed on the chip. Required when using an avatar prefix. + */ + label: string; + } + | { + /** + * Element or path used as icon to be placed before the chip label. + */ + prefix: string | SVG; + /** + * Text to be placed on the chip. Optional when using an icon prefix. + */ + label?: string; + } + | { + prefix?: undefined; + /** + * Text to be placed on the chip. + */ + label: string; + } + ) +>; -type DismissibleChipProps = CommonProps & { - /** - * Dismissible chip is used to represent information generated by user input within an interface. - */ - mode: "dismissible"; - /** - * Text to be placed on the chip. - */ - label: string; - /** - * Element, path or avatar used as icon to be placed before the chip label. - */ - prefix?: string | SVG | ChipAvatarType; - selected?: never; - disabled?: never; -}; +type DismissibleChipProps = PrettifyTypes< + CommonProps & { + /** + * Dismissible chip is used to represent information generated by user input within an interface. + */ + mode: "dismissible"; + /** + * Text to be placed on the chip. + */ + label: string; + /** + * Element, path or avatar used as icon to be placed before the chip label. + */ + prefix?: string | SVG | ChipAvatarType; + selected?: never; + disabled?: never; + } +>; -type Props = SelectableChipProps | DismissibleChipProps; +export type ChipProps = PrettifyTypes<SelectableChipProps | DismissibleChipProps>; -export default Props; +export type { ChipProps as default }; diff --git a/packages/lib/src/container/types.ts b/packages/lib/src/container/types.ts index ed2ce200b2..847e906620 100644 --- a/packages/lib/src/container/types.ts +++ b/packages/lib/src/container/types.ts @@ -1,4 +1,5 @@ import { ReactNode, Ref } from "react"; +import { PrettifyTypes } from "../common/types"; export type Spacing = { top?: string; @@ -23,21 +24,24 @@ export type BorderProperties = { style?: string; color?: string; }; -export type Border = +export type Border = PrettifyTypes< | BorderProperties | { top?: BorderProperties; right?: BorderProperties; bottom?: BorderProperties; left?: BorderProperties; - }; + } +>; -export type Outline = BorderProperties & { - offset?: string; -}; +export type Outline = PrettifyTypes< + BorderProperties & { + offset?: string; + } +>; export type OverflowValues = "visible" | "hidden" | "clip" | "scroll" | "auto"; -export type Overflow = OverflowValues | { x?: OverflowValues; y?: OverflowValues }; +export type Overflow = PrettifyTypes<OverflowValues | { x?: OverflowValues; y?: OverflowValues }>; export type ContainerProps = { /** @@ -171,3 +175,5 @@ export type StyledProps = Omit<ContainerProps, "display" | "width" | "height" | $overflow?: Overflow; $width?: string; }; + +export type { ContainerProps as default }; diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index 3e845a4965..f3ba8abb4c 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -57,28 +57,32 @@ export { HalstackProvider, HalstackLanguageContext } from "./HalstackContext"; export { default as useToast } from "./toast/useToast"; // types exports +export type { Space, Margin, SVG, Size, Shape, Color } from "./common/types"; export type { - AccordionProps as DxcAccordionProps, - AccordionItemProps as DxcAccordionItemProps, + AccordionProps as DxcAccordionProps, + AccordionItemProps as DxcAccordionItemProps, } from "./accordion/types"; export type { - AlertProps as DxcAlertProps, - AlertAction as DxcAlertAction, - AlertMessage as DxcAlertMessage, + AlertProps as DxcAlertProps, + AlertAction as DxcAlertAction, + AlertMessage as DxcAlertMessage, } from "./alert/types"; export type { AvatarProps as DxcAvatarProps, AvatarStatus as DxcAvatarStatus } from "./avatar/types"; export type { BadgeProps as DxcBadgeProps } from "./badge/types"; export type { - BreadcrumbsProps as DxcBreadcrumbsProps, - BreadcrumbsItemProps as DxcBreadcrumbsItemProps, + BreadcrumbsProps as DxcBreadcrumbsProps, + BreadcrumbsItemProps as DxcBreadcrumbsItemProps, } from "./breadcrumbs/types"; export type { - BulletedListProps as DxcBulletedListProps, - BulletedListItemProps as DxcBulletedListItemProps, + BulletedListProps as DxcBulletedListProps, + BulletedListItemProps as DxcBulletedListItemProps, } from "./bulleted-list/types"; export type { - ButtonProps as DxcButtonPropsType, - ButtonMode as DxcButtonMode, - ButtonSemantic as DxcButtonSemantic, - ButtonSize as DxcButtonSize, + ButtonProps as DxcButtonPropsType, + ButtonMode as DxcButtonMode, + ButtonSemantic as DxcButtonSemantic, + ButtonSize as DxcButtonSize, } from "./button/types"; +export type { CardProps as DxcCardProps } from "./card/types"; +export type { CheckboxProps as DxcCheckboxProps } from "./checkbox/types"; +export type { ChipProps as DxcChipProps } from "./chip/types"; From 1aacab160e91fbb22ab27a44cc6647c41aae0c66 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Wed, 14 Oct 2026 13:01:58 +0200 Subject: [PATCH 06/18] Base menu types and related components added to export --- packages/lib/src/base-menu/GroupItem.tsx | 4 +- packages/lib/src/base-menu/ItemAction.tsx | 10 +-- packages/lib/src/base-menu/MenuItem.tsx | 4 +- packages/lib/src/base-menu/Section.tsx | 4 +- packages/lib/src/base-menu/SingleItem.tsx | 4 +- packages/lib/src/base-menu/SubMenu.tsx | 4 +- packages/lib/src/base-menu/types.ts | 79 +++++++++---------- packages/lib/src/base-menu/useGroupItem.ts | 10 ++- packages/lib/src/base-menu/useItemAction.ts | 4 +- packages/lib/src/base-menu/utils.ts | 30 +++---- .../src/contextual-menu/ContextualMenu.tsx | 11 +-- packages/lib/src/contextual-menu/types.ts | 40 ++-------- packages/lib/src/header/Header.tsx | 10 +-- packages/lib/src/header/types.ts | 23 +++--- packages/lib/src/index.ts | 32 +++++++- packages/lib/src/layout/ApplicationLayout.tsx | 8 +- packages/lib/src/layout/types.ts | 8 +- packages/lib/src/sidenav/Sidenav.tsx | 4 +- packages/lib/src/sidenav/types.ts | 14 ++-- 19 files changed, 155 insertions(+), 148 deletions(-) diff --git a/packages/lib/src/base-menu/GroupItem.tsx b/packages/lib/src/base-menu/GroupItem.tsx index 8b6cdf8642..cabbeb58e7 100644 --- a/packages/lib/src/base-menu/GroupItem.tsx +++ b/packages/lib/src/base-menu/GroupItem.tsx @@ -3,12 +3,12 @@ import DxcIcon from "../icon/Icon"; import SubMenu from "./SubMenu"; import ItemAction from "./ItemAction"; import MenuItem from "./MenuItem"; -import { GroupItemProps } from "./types"; +import { BaseGroupItemProps } from "./types"; import { useGroupItem } from "./useGroupItem"; import BaseMenuContext from "./BaseMenuContext"; import DxcPopover from "../popover/Popover"; -const GroupItem = ({ items, ...props }: GroupItemProps) => { +const GroupItem = ({ items, ...props }: BaseGroupItemProps) => { const groupMenuId = `group-menu-${useId()}`; const contextValue = use(BaseMenuContext) ?? {}; const { groupSelected, isOpen, toggleOpen, hasPopOver, isHorizontal } = useGroupItem( diff --git a/packages/lib/src/base-menu/ItemAction.tsx b/packages/lib/src/base-menu/ItemAction.tsx index df7d2a0480..a6f39bcfa0 100644 --- a/packages/lib/src/base-menu/ItemAction.tsx +++ b/packages/lib/src/base-menu/ItemAction.tsx @@ -1,13 +1,13 @@ import { memo } from "react"; import styled from "@emotion/styled"; -import { ItemActionProps } from "./types"; +import { BaseItemActionProps } from "./types"; import DxcIcon from "../icon/Icon"; import { TooltipWrapper } from "../tooltip/Tooltip"; import { useItemAction } from "./useItemAction"; const Action = styled.a<{ - depthLevel: ItemActionProps["depthLevel"]; - selected: ItemActionProps["selected"]; + depthLevel: BaseItemActionProps["depthLevel"]; + selected: BaseItemActionProps["selected"]; displayGroupLines: boolean; hasPopOver?: boolean; isHorizontal?: boolean; @@ -60,7 +60,7 @@ const Icon = styled.span` } `; -const Text = styled.span<{ selected: ItemActionProps["selected"] }>` +const Text = styled.span<{ selected: BaseItemActionProps["selected"] }>` color: var(--color-fg-neutral-dark); font-family: var(--typography-font-family); font-size: var(--typography-label-m); @@ -79,7 +79,7 @@ const Control = styled.span` gap: var(--spacing-gap-s); `; -const ItemAction = memo(({ ...props }: ItemActionProps) => { +const ItemAction = memo(({ ...props }: BaseItemActionProps) => { const { hasTooltip, modifiedBadge, diff --git a/packages/lib/src/base-menu/MenuItem.tsx b/packages/lib/src/base-menu/MenuItem.tsx index b70663a489..6fad9c6975 100644 --- a/packages/lib/src/base-menu/MenuItem.tsx +++ b/packages/lib/src/base-menu/MenuItem.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; import GroupItem from "./GroupItem"; import SingleItem from "./SingleItem"; -import { MenuItemProps } from "./types"; +import { BaseMenuItemProps } from "./types"; import { isGroupItem } from "./utils"; const MenuItemContainer = styled.li` @@ -9,7 +9,7 @@ const MenuItemContainer = styled.li` gap: var(--spacing-gap-xs); `; -export default function MenuItem({ item, depthLevel = 0 }: MenuItemProps) { +export default function MenuItem({ item, depthLevel = 0 }: BaseMenuItemProps) { return ( <MenuItemContainer role="menuitem"> {isGroupItem(item) ? ( diff --git a/packages/lib/src/base-menu/Section.tsx b/packages/lib/src/base-menu/Section.tsx index 7cb5a1f14f..5a730afe41 100644 --- a/packages/lib/src/base-menu/Section.tsx +++ b/packages/lib/src/base-menu/Section.tsx @@ -2,7 +2,7 @@ import { use, useId } from "react"; import styled from "@emotion/styled"; import SubMenu from "./SubMenu"; import MenuItem from "./MenuItem"; -import { SectionProps } from "./types"; +import { BaseSectionProps } from "./types"; import BaseMenuContext from "./BaseMenuContext"; import DxcInset from "../inset/Inset"; import DxcDivider from "../divider/Divider"; @@ -21,7 +21,7 @@ const Title = styled.h2` padding: var(--spacing-padding-xxs); `; -export default function Section({ index, length, section }: SectionProps) { +export default function Section({ index, length, section }: BaseSectionProps) { const id = `section-${useId()}`; const { hasPopOver } = use(BaseMenuContext) ?? {}; return ( diff --git a/packages/lib/src/base-menu/SingleItem.tsx b/packages/lib/src/base-menu/SingleItem.tsx index c0482e574f..8699712bf4 100644 --- a/packages/lib/src/base-menu/SingleItem.tsx +++ b/packages/lib/src/base-menu/SingleItem.tsx @@ -1,9 +1,9 @@ import { use, useEffect } from "react"; import ItemAction from "./ItemAction"; -import { SingleItemProps } from "./types"; +import { BaseSingleItemProps } from "./types"; import BaseMenuContext from "./BaseMenuContext"; -export default function SingleItem({ id, onSelect, selected = false, ...props }: SingleItemProps) { +export default function SingleItem({ id, onSelect, selected = false, ...props }: BaseSingleItemProps) { const { selectedItemId, setSelectedItemId, hasPopOver, closePopOver, onSelectItem } = use(BaseMenuContext) ?? {}; const handleClick = () => { diff --git a/packages/lib/src/base-menu/SubMenu.tsx b/packages/lib/src/base-menu/SubMenu.tsx index 3874bd8859..902a7148c2 100644 --- a/packages/lib/src/base-menu/SubMenu.tsx +++ b/packages/lib/src/base-menu/SubMenu.tsx @@ -1,5 +1,5 @@ import styled from "@emotion/styled"; -import { SubMenuProps } from "./types"; +import { BaseSubMenuProps } from "./types"; import BaseMenuContext from "./BaseMenuContext"; import { use } from "react"; @@ -35,7 +35,7 @@ export default function SubMenu({ depthLevel = 0, isHorizontal = false, isPopOver = false, -}: SubMenuProps) { +}: BaseSubMenuProps) { const { displayGroupLines } = use(BaseMenuContext) ?? {}; return ( <SubMenuContainer diff --git a/packages/lib/src/base-menu/types.ts b/packages/lib/src/base-menu/types.ts index 139cd4d7e1..af4ece3db5 100644 --- a/packages/lib/src/base-menu/types.ts +++ b/packages/lib/src/base-menu/types.ts @@ -1,30 +1,30 @@ import { ButtonHTMLAttributes, Dispatch, ReactElement, ReactNode, SetStateAction } from "react"; import { SVG } from "../common/types"; -type CommonItemProps = { +type BaseCommonItemProps = { badge?: ReactElement; icon?: string | SVG; label: string; }; -type Item = CommonItemProps & { +type BaseItem = BaseCommonItemProps & { onSelect?: () => void; selected?: boolean; href?: string; renderItem?: (props: { children: ReactNode }) => ReactNode; }; -type GroupItem = CommonItemProps & { - items: (Item | GroupItem)[]; +type BaseGroupItem = BaseCommonItemProps & { + items: (BaseItem | BaseGroupItem)[]; defaultOpen?: boolean; }; -type Section = { items: (Item | GroupItem)[]; title?: string }; -type Props = { +type BaseSection = { items: (BaseItem | BaseGroupItem)[]; title?: string }; +type BaseMenuProps = { /** * Array of items to be displayed in the menu. * Each item can be a single/simple item, a group item or a section. */ - items: (Item | GroupItem)[] | Section[]; + items: (BaseItem | BaseGroupItem)[] | BaseSection[]; /** * If true the menu will be displayed with a border. */ @@ -52,41 +52,41 @@ type Props = { onSelectItem?: () => void; }; -type ItemWithId = Item & { id: number }; +type BaseItemWithId = BaseItem & { id: number }; -type GroupItemWithId = Omit<GroupItem, "items"> & { - items: (ItemWithId | GroupItemWithId)[]; +type BaseGroupItemWithId = Omit<BaseGroupItem, "items"> & { + items: (BaseItemWithId | BaseGroupItemWithId)[]; }; -type SectionWithId = { items: (ItemWithId | GroupItemWithId)[]; title?: string }; +type BaseSectionWithId = { items: (BaseItemWithId | BaseGroupItemWithId)[]; title?: string }; -type SingleItemProps = ItemWithId & { +type BaseSingleItemProps = BaseItemWithId & { depthLevel: number; }; -type GroupItemProps = GroupItemWithId & { +type BaseGroupItemProps = BaseGroupItemWithId & { depthLevel: number; }; -type MenuItemProps = { - item: ItemWithId | GroupItemWithId; +type BaseMenuItemProps = { + item: BaseItemWithId | BaseGroupItemWithId; depthLevel?: number; }; -type ItemActionProps = ButtonHTMLAttributes<HTMLAnchorElement> & { - badge?: Item["badge"]; +type BaseItemActionProps = ButtonHTMLAttributes<HTMLAnchorElement> & { + badge?: BaseItem["badge"]; collapseIcon?: ReactNode; depthLevel: number; - icon?: Item["icon"]; - label: Item["label"]; + icon?: BaseItem["icon"]; + label: BaseItem["label"]; ref?: React.Ref<HTMLAnchorElement> | undefined; - selected: Item["selected"]; - href?: Item["href"]; - renderItem?: Item["renderItem"]; + selected: BaseItem["selected"]; + href?: BaseItem["href"]; + renderItem?: BaseItem["renderItem"]; }; -type SectionProps = { - section: SectionWithId; +type BaseSectionProps = { + section: BaseSectionWithId; index: number; length: number; }; -type SubMenuProps = { +type BaseSubMenuProps = { children: ReactNode; id?: string; depthLevel?: number; @@ -105,20 +105,19 @@ type BaseMenuContextProps = { }; export type { - CommonItemProps, + BaseCommonItemProps, BaseMenuContextProps, - GroupItem, - GroupItemProps, - GroupItemWithId, - Item, - ItemActionProps, - ItemWithId, - SubMenuProps, - MenuItemProps, - Section, - SectionWithId, - SectionProps, - SingleItemProps, + BaseGroupItem, + BaseGroupItemProps, + BaseGroupItemWithId, + BaseItem, + BaseItemActionProps, + BaseItemWithId, + BaseSubMenuProps, + BaseMenuItemProps, + BaseSection, + BaseSectionWithId, + BaseSectionProps, + BaseSingleItemProps, + BaseMenuProps as default, }; - -export default Props; diff --git a/packages/lib/src/base-menu/useGroupItem.ts b/packages/lib/src/base-menu/useGroupItem.ts index 96f11608bd..e349e4cd0e 100644 --- a/packages/lib/src/base-menu/useGroupItem.ts +++ b/packages/lib/src/base-menu/useGroupItem.ts @@ -1,14 +1,18 @@ import { useId, useMemo, useState } from "react"; -import { BaseMenuContextProps, GroupItemProps } from "./types"; +import { BaseMenuContextProps, BaseGroupItemProps } from "./types"; -const isGroupSelected = (items: GroupItemProps["items"], selectedItemId?: number): boolean => +const isGroupSelected = (items: BaseGroupItemProps["items"], selectedItemId?: number): boolean => items.some((item) => { if ("items" in item) return isGroupSelected(item.items, selectedItemId); else if (selectedItemId !== -1) return item.id === selectedItemId; else return !!item.selected; }); -export const useGroupItem = (items: GroupItemProps["items"], context: BaseMenuContextProps, defaultOpen?: boolean) => { +export const useGroupItem = ( + items: BaseGroupItemProps["items"], + context: BaseMenuContextProps, + defaultOpen?: boolean +) => { const groupMenuId = `group-menu-${useId()}`; const { selectedItemId, hasPopOver } = context ?? {}; const groupSelected = useMemo(() => isGroupSelected(items, selectedItemId), [items, selectedItemId]); diff --git a/packages/lib/src/base-menu/useItemAction.ts b/packages/lib/src/base-menu/useItemAction.ts index 46ac53d040..a394986ca5 100644 --- a/packages/lib/src/base-menu/useItemAction.ts +++ b/packages/lib/src/base-menu/useItemAction.ts @@ -1,8 +1,8 @@ import { useState, use, cloneElement, ReactNode, ReactElement } from "react"; import BaseMenuContext from "./BaseMenuContext"; -import { ItemActionProps } from "./types"; +import { BaseItemActionProps } from "./types"; -export function useItemAction({ badge, renderItem }: ItemActionProps) { +export function useItemAction({ badge, renderItem }: BaseItemActionProps) { const [hasTooltip, setHasTooltip] = useState(false); const modifiedBadge = badge && cloneElement(badge as ReactElement<{ size?: string }>, { size: "small" }); const { displayControlsAfter, hasPopOver, displayGroupLines, isHorizontal } = use(BaseMenuContext) ?? {}; diff --git a/packages/lib/src/base-menu/utils.ts b/packages/lib/src/base-menu/utils.ts index 77db32b032..37182c3684 100644 --- a/packages/lib/src/base-menu/utils.ts +++ b/packages/lib/src/base-menu/utils.ts @@ -1,36 +1,36 @@ import ContextualMenuPropsType, { - GroupItem, - GroupItemProps, - GroupItemWithId, - Item, - ItemWithId, - Section as SectionType, - SectionWithId, + BaseGroupItem, + BaseGroupItemProps, + BaseGroupItemWithId, + BaseItem, + BaseItemWithId, + BaseSection, + BaseSectionWithId, } from "./types"; -export const isGroupItem = (item: Item | GroupItem): item is GroupItem => "items" in item; +export const isGroupItem = (item: BaseItem | BaseGroupItem): item is BaseGroupItem => "items" in item; -export const isSection = (item: SectionType | Item | GroupItem): item is SectionType => +export const isSection = (item: BaseSection | BaseItem | BaseGroupItem): item is BaseSection => "items" in item && !("label" in item); export const addIdToItems = ( items: ContextualMenuPropsType["items"] -): (ItemWithId | GroupItemWithId | SectionWithId)[] => { +): (BaseItemWithId | BaseGroupItemWithId | BaseSectionWithId)[] => { let accId = 0; const innerAddIdToItems = ( items: ContextualMenuPropsType["items"] - ): (ItemWithId | GroupItemWithId | SectionWithId)[] => - items.map((item: Item | GroupItem | SectionType) => + ): (BaseItemWithId | BaseGroupItemWithId | BaseSectionWithId)[] => + items.map((item: BaseItem | BaseGroupItem | BaseSection) => isSection(item) - ? ({ ...item, items: innerAddIdToItems(item.items) } as SectionWithId) + ? ({ ...item, items: innerAddIdToItems(item.items) } as BaseSectionWithId) : isGroupItem(item) - ? ({ ...item, items: innerAddIdToItems(item.items) } as GroupItemWithId) + ? ({ ...item, items: innerAddIdToItems(item.items) } as BaseGroupItemWithId) : { ...item, id: accId++ } ); return innerAddIdToItems(items); }; -export const isGroupSelected = (items: GroupItemProps["items"], selectedItemId?: number): boolean => +export const isGroupSelected = (items: BaseGroupItemProps["items"], selectedItemId?: number): boolean => items.some((item) => { if ("items" in item) return isGroupSelected(item.items, selectedItemId); else if (selectedItemId !== -1) return item.id === selectedItemId; diff --git a/packages/lib/src/contextual-menu/ContextualMenu.tsx b/packages/lib/src/contextual-menu/ContextualMenu.tsx index 0ce3a683de..c34e8eef23 100644 --- a/packages/lib/src/contextual-menu/ContextualMenu.tsx +++ b/packages/lib/src/contextual-menu/ContextualMenu.tsx @@ -3,10 +3,11 @@ import styled from "@emotion/styled"; import MenuItem from "../base-menu/MenuItem"; import Section from "../base-menu/Section"; import SubMenu from "../base-menu/SubMenu"; -import ContextualMenuContext from "../base-menu/BaseMenuContext"; -import ContextualMenuPropsType, { GroupItemWithId, ItemWithId, SectionWithId } from "./types"; +import ContextualMenuContext from "./ContextualMenuContext"; +import { ContextualMenuProps } from "./types"; import scrollbarStyles from "../styles/scroll"; import { addIdToItems, isSection } from "../base-menu/utils"; +import { BaseGroupItemWithId, BaseItemWithId, BaseSectionWithId } from "../base-menu/types"; const ContextualMenu = styled.div` box-sizing: border-box; @@ -24,7 +25,7 @@ const ContextualMenu = styled.div` ${scrollbarStyles} `; -export default function DxcContextualMenu({ items }: ContextualMenuPropsType) { +export default function DxcContextualMenu({ items }: ContextualMenuProps) { const [firstUpdate, setFirstUpdate] = useState(true); const [selectedItemId, setSelectedItemId] = useState(-1); const contextualMenuRef = useRef<HTMLDivElement | null>(null); @@ -48,12 +49,12 @@ export default function DxcContextualMenu({ items }: ContextualMenuPropsType) { <ContextualMenu ref={contextualMenuRef}> <ContextualMenuContext value={contextValue}> {itemsWithId[0] && isSection(itemsWithId[0]) ? ( - (itemsWithId as SectionWithId[]).map((item, index) => ( + (itemsWithId as BaseSectionWithId[]).map((item, index) => ( <Section key={`section-${index}`} section={item} index={index} length={itemsWithId.length} /> )) ) : ( <SubMenu> - {(itemsWithId as (GroupItemWithId | ItemWithId)[]).map((item, index) => ( + {(itemsWithId as (BaseGroupItemWithId | BaseItemWithId)[]).map((item, index) => ( <MenuItem item={item} key={`${item.label}-${index}`} /> ))} </SubMenu> diff --git a/packages/lib/src/contextual-menu/types.ts b/packages/lib/src/contextual-menu/types.ts index 194c79aaed..2bd21d1dcc 100644 --- a/packages/lib/src/contextual-menu/types.ts +++ b/packages/lib/src/contextual-menu/types.ts @@ -1,37 +1,9 @@ -import BaseProps, { - BaseMenuContextProps, - GroupItem, - GroupItemProps, - GroupItemWithId, - Item as BaseItem, - ItemActionProps as BaseItemActionProps, - ItemWithId, - SubMenuProps, - MenuItemProps, - Section, - SectionWithId, - SectionProps, - SingleItemProps, -} from "../base-menu/types"; +import BaseProps, { BaseMenuContextProps } from "../base-menu/types"; -type Item = Omit<BaseItem, "href" | "renderItem" | "selected">; -type Props = Omit<BaseProps, "displayBorder" | "displayGroupLines" | "displayControlsAfter" | "hasPopOver">; -type ItemActionProps = Omit<BaseItemActionProps, "href" | "renderItem">; +type ContextualMenuProps = Omit< + BaseProps, + "displayBorder" | "displayGroupLines" | "displayControlsAfter" | "hasPopOver" +>; type ContextualMenuContextProps = Omit<BaseMenuContextProps, "hasPopOver">; -export type { - ContextualMenuContextProps, - GroupItem, - GroupItemProps, - GroupItemWithId, - Item, - ItemActionProps, - ItemWithId, - SubMenuProps, - MenuItemProps, - Section, - SectionWithId, - SectionProps, - SingleItemProps, - Props as default, -}; +export type { ContextualMenuProps, ContextualMenuContextProps, ContextualMenuProps as default }; diff --git a/packages/lib/src/header/Header.tsx b/packages/lib/src/header/Header.tsx index 1f452a8471..2898633d7b 100644 --- a/packages/lib/src/header/Header.tsx +++ b/packages/lib/src/header/Header.tsx @@ -1,11 +1,11 @@ import styled from "@emotion/styled"; import DxcGrid from "../grid/Grid"; -import HeaderProps from "./types"; +import { HeaderProps } from "./types"; import DxcImage from "../image/Image"; import DxcDivider from "../divider/Divider"; import DxcHeading from "../heading/Heading"; import { isGroupItem } from "../base-menu/utils"; -import { GroupItem, Item } from "../base-menu/types"; +import { BaseGroupItem, BaseItem } from "../base-menu/types"; import { JSX, use, useEffect, useMemo, useState } from "react"; import DxcNavigationTree from "../navigation-tree/NavigationTree"; import { responsiveSizes } from "../common/variables"; @@ -114,13 +114,13 @@ const Overlay = styled.div` * @param level current level of recursion. * @return Processed navigation items with limited levels. */ -const sanitizeNavItems = (navItems: HeaderProps["navItems"], level?: number): (GroupItem | Item)[] => { +const sanitizeNavItems = (navItems: HeaderProps["navItems"], level?: number): (BaseGroupItem | BaseItem)[] => { if (!navItems) return []; if (!level) level = 0; - const sanitizedItems = navItems.reduce<(GroupItem | Item)[]>((acc, item) => { + const sanitizedItems = navItems.reduce<(BaseGroupItem | BaseItem)[]>((acc, item) => { if (isGroupItem(item)) { if (level < LEVEL_LIMIT) { - const processedGroup: GroupItem = { + const processedGroup: BaseGroupItem = { ...item, items: sanitizeNavItems(item.items, level + 1), }; diff --git a/packages/lib/src/header/types.ts b/packages/lib/src/header/types.ts index b8ba097537..64e46f9bff 100644 --- a/packages/lib/src/header/types.ts +++ b/packages/lib/src/header/types.ts @@ -1,21 +1,24 @@ import { ReactNode } from "react"; -import { CommonItemProps, Item } from "../base-menu/types"; +import { BaseCommonItemProps, BaseItem } from "../base-menu/types"; import { SearchBarProps } from "../search-bar/types"; +import { PrettifyTypes } from "../common/types"; -type GroupItem = CommonItemProps & { - items: Item[]; -}; +export type HeaderGroupItem = PrettifyTypes< + BaseCommonItemProps & { + items: BaseItem[]; + } +>; -type MainNavPropsType = (GroupItem | Item)[]; +export type HeaderMainNavPropsType = (HeaderGroupItem | PrettifyTypes<BaseItem>)[]; -type SearchBarHeaderProps = Omit<SearchBarProps, "autoFocus" | "disabled">; +export type HeaderSearchBarProps = Omit<SearchBarProps, "autoFocus" | "disabled">; -type Props = { +export type HeaderProps = { appTitle?: string; - navItems?: MainNavPropsType; + navItems?: HeaderMainNavPropsType; responsiveBottomContent?: ReactNode; - searchBar?: SearchBarHeaderProps; + searchBar?: HeaderSearchBarProps; sideContent?: ReactNode | ((isResponsive: boolean) => ReactNode); }; -export default Props; +export type { HeaderProps as default }; diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index f3ba8abb4c..807a5d28b6 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -57,7 +57,14 @@ export { HalstackProvider, HalstackLanguageContext } from "./HalstackContext"; export { default as useToast } from "./toast/useToast"; // types exports -export type { Space, Margin, SVG, Size, Shape, Color } from "./common/types"; +export type { + Space as DxcSpace, + Margin as DxcMargin, + SVG as DxcSVG, + Size as DxcSize, + Shape as DxcShape, + Color as DxcColor, +} from "./common/types"; export type { AccordionProps as DxcAccordionProps, AccordionItemProps as DxcAccordionItemProps, @@ -67,8 +74,17 @@ export type { AlertAction as DxcAlertAction, AlertMessage as DxcAlertMessage, } from "./alert/types"; +export type { + ApplicationLayoutProps as DxcAppLayoutProps, + AppLayoutMainProps as DxcAppLayoutMainProps, +} from "./layout/types"; export type { AvatarProps as DxcAvatarProps, AvatarStatus as DxcAvatarStatus } from "./avatar/types"; export type { BadgeProps as DxcBadgeProps } from "./badge/types"; +export type { + BaseItem as DxcBaseItem, + BaseGroupItem as DxcBaseGroupItem, + BaseSection as DxcBaseSection, +} from "./base-menu/types"; export type { BreadcrumbsProps as DxcBreadcrumbsProps, BreadcrumbsItemProps as DxcBreadcrumbsItemProps, @@ -78,7 +94,7 @@ export type { BulletedListItemProps as DxcBulletedListItemProps, } from "./bulleted-list/types"; export type { - ButtonProps as DxcButtonPropsType, + ButtonProps as DxcButtonProps, ButtonMode as DxcButtonMode, ButtonSemantic as DxcButtonSemantic, ButtonSize as DxcButtonSize, @@ -86,3 +102,15 @@ export type { export type { CardProps as DxcCardProps } from "./card/types"; export type { CheckboxProps as DxcCheckboxProps } from "./checkbox/types"; export type { ChipProps as DxcChipProps } from "./chip/types"; +export type { ContextualMenuProps as DxcContextualMenuProps } from "./contextual-menu/types"; +export type { + HeaderProps as DxcHeaderProps, + HeaderMainNavPropsType as DxcHeaderMainNavPropsType, + HeaderSearchBarProps as DxcHeaderSearchBarProps, + HeaderGroupItem as DxcHeaderGroupItem, +} from "./header/types"; +export type { + SidenavProps as DxcSidenavProps, + SidenavSection as DxcSidenavSection, + SidenavSearchbarProps as DxcSidenavSearchbarProps, +} from "./sidenav/types"; diff --git a/packages/lib/src/layout/ApplicationLayout.tsx b/packages/lib/src/layout/ApplicationLayout.tsx index 546b396091..2132451cfe 100644 --- a/packages/lib/src/layout/ApplicationLayout.tsx +++ b/packages/lib/src/layout/ApplicationLayout.tsx @@ -3,7 +3,7 @@ import styled from "@emotion/styled"; import DxcFooter from "../footer/Footer"; import DxcHeader from "../header/Header"; import DxcSidenav from "../sidenav/Sidenav"; -import ApplicationLayoutPropsType, { AppLayoutMainPropsType } from "./types"; +import { ApplicationLayoutProps, AppLayoutMainProps } from "./types"; import { bottomLinks, findChildType, socialLinks, year } from "./utils"; import ApplicationLayoutContext from "./ApplicationLayoutContext"; import { responsiveSizes } from "../common/variables"; @@ -62,9 +62,9 @@ const FooterContainer = styled.div` width: 100%; `; -const Main = ({ children }: AppLayoutMainPropsType): JSX.Element => <div>{children}</div>; +const Main = ({ children }: AppLayoutMainProps): JSX.Element => <div>{children}</div>; -const DxcApplicationLayout = ({ logo, header, sidenav, footer, children }: ApplicationLayoutPropsType): JSX.Element => { +const DxcApplicationLayout = ({ logo, header, sidenav, footer, children }: ApplicationLayoutProps): JSX.Element => { const [headerHeight, setHeaderHeight] = useState("0px"); const [hideMainContent, setHideMainContent] = useState(false); const themedLogos = use(HalstackLogosContext); @@ -80,7 +80,7 @@ const DxcApplicationLayout = ({ logo, header, sidenav, footer, children }: Appli ); const contextValue = useMemo(() => { - const logoToUse: ApplicationLayoutPropsType["logo"] = { + const logoToUse: ApplicationLayoutProps["logo"] = { src: logo?.src || themedLogos?.mainLogo || "", alt: logo?.alt || "", }; diff --git a/packages/lib/src/layout/types.ts b/packages/lib/src/layout/types.ts index 23da6ce3ab..9c36e9bd34 100644 --- a/packages/lib/src/layout/types.ts +++ b/packages/lib/src/layout/types.ts @@ -1,7 +1,7 @@ import { ReactElement, ReactNode } from "react"; import { SVG } from "../common/types"; -export type AppLayoutMainPropsType = { +export type AppLayoutMainProps = { /** * Everything between the tags will be displayed as the content of the main part of the application. */ @@ -53,7 +53,7 @@ export type ApplicationLayoutContextType = { setHideMainContent: (hide: boolean) => void; }; -type ApplicationLayoutPropsType = { +export type ApplicationLayoutProps = { /** * Logo properties. */ @@ -73,7 +73,7 @@ type ApplicationLayoutPropsType = { /** * Use the DxcApplicationLayout.Main provided to render main content. */ - children: ReactElement<AppLayoutMainPropsType>; + children: ReactElement<AppLayoutMainProps>; }; -export default ApplicationLayoutPropsType; +export type { ApplicationLayoutProps as default }; diff --git a/packages/lib/src/sidenav/Sidenav.tsx b/packages/lib/src/sidenav/Sidenav.tsx index 6d6bf12069..3ee2bc87bf 100644 --- a/packages/lib/src/sidenav/Sidenav.tsx +++ b/packages/lib/src/sidenav/Sidenav.tsx @@ -1,6 +1,6 @@ import styled from "@emotion/styled"; import DxcFlex from "../flex/Flex"; -import SidenavPropsType from "./types"; +import { SidenavProps } from "./types"; import DxcDivider from "../divider/Divider"; import DxcButton from "../button/Button"; import DxcImage from "../image/Image"; @@ -102,7 +102,7 @@ const DxcSidenav = ({ defaultExpanded, onExpandedChange, searchBar, -}: SidenavPropsType): JSX.Element => { +}: SidenavProps): JSX.Element => { const isBelowLarge = useBreakpoint("large"); const isBelowMedium = useBreakpoint("medium"); const { logo, headerExists, setHideMainContent } = use(ApplicationLayoutContext); diff --git a/packages/lib/src/sidenav/types.ts b/packages/lib/src/sidenav/types.ts index 460ee830a5..7a762220f1 100644 --- a/packages/lib/src/sidenav/types.ts +++ b/packages/lib/src/sidenav/types.ts @@ -1,12 +1,12 @@ import { ReactNode } from "react"; import { SearchBarProps } from "../search-bar/types"; -import { GroupItem, Item } from "../base-menu/types"; +import { BaseGroupItem, BaseItem } from "../base-menu/types"; -type Section = { items: (Item | GroupItem)[]; title?: string }; +export type SidenavSection = { items: (BaseItem | BaseGroupItem)[]; title?: string }; -type SearchbarSidenavProps = Omit<SearchBarProps, "autoFocus" | "disabled" | "onCancel">; +export type SidenavSearchbarProps = Omit<SearchBarProps, "autoFocus" | "disabled" | "onCancel">; -type Props = { +export type SidenavProps = { /** * The content rendered in the bottom part of the sidenav, under the navigation menu. */ @@ -32,7 +32,7 @@ type Props = { * Array of items to be displayed in the navigation menu. * Each item can be a single/simple item, a group item or a section. */ - navItems?: (Item | GroupItem)[] | Section[]; + navItems?: (BaseItem | BaseGroupItem)[] | SidenavSection[]; /** * Function called when the expansion state of the sidenav changes. */ @@ -40,11 +40,11 @@ type Props = { /** * When provided, a search bar will be rendered at the top of the sidenav. */ - searchBar?: SearchbarSidenavProps; + searchBar?: SidenavSearchbarProps; /** * The additional content rendered in the upper part of the sidenav, under the branding. */ topContent?: ReactNode; }; -export default Props; +export type { SidenavProps as default }; From ab6dabaf3903aca47cb34de8895d3e268a080f3a Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Thu, 15 Oct 2026 12:04:55 +0200 Subject: [PATCH 07/18] Export types up to Inset --- packages/lib/src/base-menu/types.ts | 1 + packages/lib/src/data-grid/DataGrid.tsx | 19 ++- packages/lib/src/data-grid/types.ts | 142 +++++++++-------- packages/lib/src/data-grid/utils.tsx | 181 +++++++++++----------- packages/lib/src/date-input/DateInput.tsx | 14 +- packages/lib/src/date-input/types.ts | 4 +- packages/lib/src/dialog/types.ts | 4 +- packages/lib/src/divider/Divider.tsx | 6 +- packages/lib/src/divider/types.ts | 4 +- packages/lib/src/dropdown/Dropdown.tsx | 22 +-- packages/lib/src/dropdown/types.ts | 16 +- packages/lib/src/file-input/FileInput.tsx | 20 +-- packages/lib/src/file-input/types.ts | 6 +- packages/lib/src/flex/Flex.tsx | 4 +- packages/lib/src/flex/types.ts | 141 +++++++++-------- packages/lib/src/footer/Footer.tsx | 12 +- packages/lib/src/footer/types.ts | 16 +- packages/lib/src/grid/Grid.tsx | 6 +- packages/lib/src/grid/types.ts | 148 +++++++++--------- packages/lib/src/heading/types.ts | 4 +- packages/lib/src/heading/utils.ts | 6 +- packages/lib/src/image/Image.tsx | 6 +- packages/lib/src/image/types.ts | 4 +- packages/lib/src/index.ts | 35 +++++ packages/lib/src/inset/Inset.tsx | 4 +- packages/lib/src/inset/types.ts | 4 +- 26 files changed, 447 insertions(+), 382 deletions(-) diff --git a/packages/lib/src/base-menu/types.ts b/packages/lib/src/base-menu/types.ts index af4ece3db5..c8da76d92a 100644 --- a/packages/lib/src/base-menu/types.ts +++ b/packages/lib/src/base-menu/types.ts @@ -119,5 +119,6 @@ export type { BaseSectionWithId, BaseSectionProps, BaseSingleItemProps, + BaseMenuProps, BaseMenuProps as default, }; diff --git a/packages/lib/src/data-grid/DataGrid.tsx b/packages/lib/src/data-grid/DataGrid.tsx index fb8e747f76..74c5244921 100644 --- a/packages/lib/src/data-grid/DataGrid.tsx +++ b/packages/lib/src/data-grid/DataGrid.tsx @@ -1,7 +1,7 @@ import { JSX, useEffect, useMemo, useState } from "react"; import { DataGrid, SortColumn } from "react-data-grid"; import styled from "@emotion/styled"; -import DataGridPropsType, { HierarchyGridRow, GridRow, ExpandableGridRow } from "./types"; +import type { DataGridProps, DataGridHierarchyRow, DataGridRow, DataGridExpandableRow } from "./types"; import "react-data-grid/lib/styles.css"; import { convertToRDGColumns, @@ -177,8 +177,10 @@ const DxcDataGrid = ({ onPageChange, totalItems, defaultPage = 1, -}: DataGridPropsType): JSX.Element => { - const [rowsToRender, setRowsToRender] = useState<GridRow[] | HierarchyGridRow[] | ExpandableGridRow[]>([...rows]); +}: DataGridProps): JSX.Element => { + const [rowsToRender, setRowsToRender] = useState<DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[]>([ + ...rows, + ]); const [page, changePage] = useState(defaultPage); const [colHeight, setColHeight] = useState(36); const [loadingChildren, setLoadingChildren] = useState<(string | number)[]>([]); @@ -232,11 +234,8 @@ const DxcDataGrid = ({ ...expectedColumns, ]; } - const rowHasHierarchy = (row: GridRow | HierarchyGridRow): row is HierarchyGridRow => { - return ( - (Array.isArray(row.childRows) && row.childRows?.length > 0) || - typeof (row as HierarchyGridRow)?.childrenTrigger === "function" - ); + const rowHasHierarchy = (row: DataGridRow | DataGridHierarchyRow): row is DataGridHierarchyRow => { + return (Array.isArray(row.childRows) && row.childRows?.length > 0) || typeof row?.childrenTrigger === "function"; }; if (!expandable && rows.some((row) => rowHasHierarchy(row)) && uniqueRowId) { // only the first column will be clickable and will expand the rows @@ -366,14 +365,14 @@ const DxcDataGrid = ({ }); }; - const onRowsChange = (newRows: GridRow[] | HierarchyGridRow[] | ExpandableGridRow[]) => { + const onRowsChange = (newRows: DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[]) => { // call function to change rows, like when they have been edited if (typeof onGridRowsChange === "function") { onGridRowsChange(newRows); } }; - const sortedRows = useMemo((): readonly GridRow[] | HierarchyGridRow[] | ExpandableGridRow[] => { + const sortedRows = useMemo((): readonly DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[] => { const sortFunctions = getCustomSortFn(columns); if (!onSort) { if (sortColumns.length > 0 && uniqueRowId) { diff --git a/packages/lib/src/data-grid/types.ts b/packages/lib/src/data-grid/types.ts index 1a750971a9..013e8d3be9 100644 --- a/packages/lib/src/data-grid/types.ts +++ b/packages/lib/src/data-grid/types.ts @@ -1,7 +1,8 @@ import { ReactNode } from "react"; import { SortColumn } from "react-data-grid"; +import { PrettifyTypes } from "../common/types"; -export type GridColumn = { +type DataGridColumn = { /** * Key that will be rendered from each row in rows. */ @@ -40,67 +41,71 @@ export type GridColumn = { alignment?: "left" | "right" | "center"; }; -export type GridRow = { +type DataGridRow = { /** * List of rows that will be rendered in each cell based on the key in each column. */ [key: string]: ReactNode | undefined; }; -export type HierarchyGridRow = GridRow & { - /** - * Array of child rows nested under this row, enabling hierarchical (tree-like) structures. - * These child rows will be displayed when the parent row is expanded. - */ - childRows?: HierarchyGridRow[] | GridRow[]; - /** - * Function called when a row with children is expanded or collapsed (based on the value of `open`). - * Returns (or resolves to) the array of child rows nested under this row to display when expanded. - */ - childrenTrigger?: ( - open?: boolean, - triggerRow?: HierarchyGridRow - ) => (HierarchyGridRow[] | GridRow[]) | Promise<HierarchyGridRow[] | GridRow[]>; - /** - * Indicates whether child rows are currently being loaded. - */ - loadingChildren?: boolean; - /** - * Indicates the level of nesting for this row in the hierarchy. - */ - rowLevel?: number; - /** - * Reference to the parent row's unique identifier. - */ - parentKey?: string | number; - /** - * Indicates whether child rows are currently visible. - */ - visibleChildren?: boolean; -}; +type DataGridHierarchyRow = PrettifyTypes< + DataGridRow & { + /** + * Array of child rows nested under this row, enabling hierarchical (tree-like) structures. + * These child rows will be displayed when the parent row is expanded. + */ + childRows?: DataGridHierarchyRow[] | DataGridRow[]; + /** + * Function called when a row with children is expanded or collapsed (based on the value of `open`). + * Returns (or resolves to) the array of child rows nested under this row to display when expanded. + */ + childrenTrigger?: ( + open?: boolean, + triggerRow?: DataGridHierarchyRow + ) => (DataGridHierarchyRow[] | DataGridRow[]) | Promise<DataGridHierarchyRow[] | DataGridRow[]>; + /** + * Indicates whether child rows are currently being loaded. + */ + loadingChildren?: boolean; + /** + * Indicates the level of nesting for this row in the hierarchy. + */ + rowLevel?: number; + /** + * Reference to the parent row's unique identifier. + */ + parentKey?: string | number; + /** + * Indicates whether child rows are currently visible. + */ + visibleChildren?: boolean; + } +>; -export type ExpandableGridRow = GridRow & { - expandedContent?: ReactNode; - expandedContentHeight?: number; - contentIsExpanded?: boolean; -}; +type DataGridExpandableRow = PrettifyTypes< + DataGridRow & { + expandedContent?: ReactNode; + expandedContentHeight?: number; + contentIsExpanded?: boolean; + } +>; -export type ExpandableRows = { - rows: ExpandableGridRow[]; +type DataGridExpandableRows = { + rows: DataGridExpandableRow[]; /** * Whether the rows can expand or not. */ expandable: true; /** - * This prop indicates the unique key that can be used to identify each row. This prop is mandatory if selectable is set to true, expandable is set to true or rows is of type HierarchyGridRow[]. + * This prop indicates the unique key that can be used to identify each row. This prop is mandatory if selectable is set to true, expandable is set to true or rows is of type DataGridHierarchyRow[]. */ uniqueRowId: string; }; -export type HierarchyRows = { - rows: HierarchyGridRow[]; +type DataGridHierarchyRows = { + rows: DataGridHierarchyRow[]; /** - * This prop indicates the unique key that can be used to identify each row. This prop is mandatory if selectable is set to true, expandable is set to true or rows is of type HierarchyGridRow[]. + * This prop indicates the unique key that can be used to identify each row. This prop is mandatory if selectable is set to true, expandable is set to true or rows is of type DataGridHierarchyRow[]. */ uniqueRowId: string; /** @@ -109,7 +114,7 @@ export type HierarchyRows = { expandable?: false; }; -export type SelectableGridProps = +type DataGridSelectableProps = | { /** * Whether the rows are selectable or not. @@ -124,7 +129,7 @@ export type SelectableGridProps = */ onSelectRows: (selectedRows: Set<number | string>) => void; /** - * This prop indicates the unique key that can be used to identify each row. This prop is mandatory if selectable is set to true, expandable is set to true or rows is of type HierarchyGridRow[]. + * This prop indicates the unique key that can be used to identify each row. This prop is mandatory if selectable is set to true, expandable is set to true or rows is of type DataGridHierarchyRow[]. */ uniqueRowId: string; } @@ -135,7 +140,7 @@ export type SelectableGridProps = uniqueRowId?: string; }; -type PaginatedProps = { +type DataGridPaginatedProps = { /** * If true, paginator will be displayed. */ @@ -171,7 +176,7 @@ type PaginatedProps = { defaultPage?: number; }; -type NonPaginatedProps = { +type DataGridNonPaginatedProps = { /** * If true, paginator will be displayed. */ @@ -207,16 +212,16 @@ type NonPaginatedProps = { defaultPage?: never; }; -export type CommonProps = { - columns: GridColumn[]; +type CommonProps = { + columns: DataGridColumn[]; /** * Extra row that will be always visible. */ - summaryRow?: GridRow; + summaryRow?: DataGridRow; /** * Function called whenever a cell is edited. */ - onGridRowsChange?: (_rows: GridRow[] | HierarchyGridRow[] | ExpandableGridRow[]) => void; + onGridRowsChange?: (_rows: DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[]) => void; /** * Function called whenever a column is sorted. Receives the sorted * column and direction, or `undefined` if no sorting is applied. @@ -224,20 +229,33 @@ export type CommonProps = { onSort?: (_sortColumn?: SortColumn) => void; }; -export type BasicGridProps = { - rows: GridRow[]; +type DataGridBasicProps = { + rows: DataGridRow[]; /** * Whether the rows can expand or not. */ expandable?: false; }; -type Props = CommonProps & - (PaginatedProps | NonPaginatedProps) & - ( - | (BasicGridProps & SelectableGridProps) - | (ExpandableRows & SelectableGridProps) - | (HierarchyRows & SelectableGridProps) - ); +type DataGridProps = PrettifyTypes< + CommonProps & + (DataGridPaginatedProps | DataGridNonPaginatedProps) & + ( + | (DataGridBasicProps & DataGridSelectableProps) + | (DataGridExpandableRows & DataGridSelectableProps) + | (DataGridHierarchyRows & DataGridSelectableProps) + ) +>; -export default Props; +export type { + DataGridColumn, + DataGridRow, + DataGridHierarchyRow, + DataGridExpandableRow, + DataGridExpandableRows, + DataGridHierarchyRows, + DataGridSelectableProps, + DataGridBasicProps, + DataGridProps, + DataGridProps as default, +}; diff --git a/packages/lib/src/data-grid/utils.tsx b/packages/lib/src/data-grid/utils.tsx index be9e1958b8..ff49ab15e5 100644 --- a/packages/lib/src/data-grid/utils.tsx +++ b/packages/lib/src/data-grid/utils.tsx @@ -3,19 +3,22 @@ import { Column, RenderSortStatusProps, SortColumn, renderTextEditor } from "rea import DxcActionIcon from "../action-icon/ActionIcon"; import DxcCheckbox from "../checkbox/Checkbox"; import DxcIcon from "../icon/Icon"; -import { GridColumn, HierarchyGridRow, GridRow, ExpandableGridRow } from "./types"; +import { DataGridColumn, DataGridHierarchyRow, DataGridRow, DataGridExpandableRow } from "./types"; import DxcSpinner from "../spinner/Spinner"; /** * Converts grid columns into react-data-grid column format. - * @param {GridColumn} gridColumn - Object representing the properties of a grid column. - * @param {GridRow} [summaryRow] - Optional summary row to render at the end. - * @returns {Column<GridRow | HierarchyGridRow | ExpandableGridRow, GridRow | HierarchyGridRow | ExpandableGridRow>} Formatted column object for react-data-grid. + * @param {DataGridColumn} gridColumn - Object representing the properties of a grid column. + * @param {DataGridRow} [summaryRow] - Optional summary row to render at the end. + * @returns {Column<DataGridRow | DataGridHierarchyRow | DataGridExpandableRow, DataGridRow | DataGridHierarchyRow | DataGridExpandableRow>} Formatted column object for react-data-grid. */ export const convertToRDGColumns = ( - gridColumn: GridColumn, - summaryRow?: GridRow -): Column<GridRow | HierarchyGridRow | ExpandableGridRow, GridRow | HierarchyGridRow | ExpandableGridRow> => ({ + gridColumn: DataGridColumn, + summaryRow?: DataGridRow +): Column< + DataGridRow | DataGridHierarchyRow | DataGridExpandableRow, + DataGridRow | DataGridHierarchyRow | DataGridExpandableRow +> => ({ key: gridColumn.key, name: gridColumn.label, resizable: gridColumn.resizable, @@ -58,11 +61,11 @@ export const renderSortStatus = ({ sortDirection }: RenderSortStatusProps) => ( /** * Expands a given row by inserting a new child row with the expanded content. - * @param {ExpandableGridRow} row - The row object to expand. - * @param {ExpandableGridRow[]} rows - The current list of all rows (as rendered). + * @param {DataGridExpandableRow} row - The row object to expand. + * @param {DataGridExpandableRow[]} rows - The current list of all rows (as rendered). * @param {string} uniqueRowId - Unique identifier key used for each row. */ -export const expandRow = (row: ExpandableGridRow, rows: ExpandableGridRow[], uniqueRowId: string) => { +export const expandRow = (row: DataGridExpandableRow, rows: DataGridExpandableRow[], uniqueRowId: string) => { const rowIndex = rows.findIndex((r) => r === row); addRow(rows, rowIndex + 1, { isExpandedChildContent: true, @@ -75,10 +78,10 @@ export const expandRow = (row: ExpandableGridRow, rows: ExpandableGridRow[], uni /** * Collapses a given row by removing its expanded child row. - * @param {ExpandableGridRow} row - The row object to collapse. - * @param {ExpandableGridRow[]} rows - The current list of all rows (as rendered). + * @param {DataGridExpandableRow} row - The row object to collapse. + * @param {DataGridExpandableRow[]} rows - The current list of all rows (as rendered). */ -export const collapseRow = (row: ExpandableGridRow, rows: ExpandableGridRow[]) => { +export const collapseRow = (row: DataGridExpandableRow, rows: DataGridExpandableRow[]) => { const rowIndex = rows.findIndex((r) => r === row); const newRows = [...rows]; deleteRow(newRows, rowIndex + 1); @@ -87,17 +90,17 @@ export const collapseRow = (row: ExpandableGridRow, rows: ExpandableGridRow[]) = /** * Renders an expandable trigger icon that toggles row expansion. - * @param {ExpandableGridRow} row - Row object that can be expanded or collapsed. - * @param {ExpandableGridRow[]} rows - List of all rows. + * @param {DataGridExpandableRow} row - Row object that can be expanded or collapsed. + * @param {DataGridExpandableRow[]} rows - List of all rows. * @param {string} uniqueRowId - Unique identifier for each row. * @param {Function} setRowsToRender - Function to update the rows being rendered. * @returns {JSX.Element} Icon with functionality to toggle the expanded content of the row. */ export const renderExpandableTrigger = ( - row: ExpandableGridRow, - rows: ExpandableGridRow[], + row: DataGridExpandableRow, + rows: DataGridExpandableRow[], uniqueRowId: string, - setRowsToRender: (_value: SetStateAction<GridRow[] | ExpandableGridRow[] | HierarchyGridRow[]>) => void + setRowsToRender: (_value: SetStateAction<DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[]>) => void ) => ( <DxcActionIcon size="xsmall" @@ -121,22 +124,24 @@ export const renderExpandableTrigger = ( ); /** - * Determines if the given row is a `HierarchyGridRow`. + * Determines if the given row is a `DataGridHierarchyRow`. * - * A `HierarchyGridRow` is identified by having a `childRows` property + * A `DataGridHierarchyRow` is identified by having a `childRows` property * that is an array with at least one element. * - * @param {GridRow} row - The row to check. - * @returns {row is HierarchyGridRow & { childRows: HierarchyGridRow[] | GridRow[] }} - * Returns `true` if the row is a `HierarchyGridRow` with `childRows` defined, otherwise `false`. + * @param {DataGridRow} row - The row to check. + * @returns {row is DataGridHierarchyRow & { childRows: DataGridHierarchyRow[] | DataGridRow[] }} + * Returns `true` if the row is a `DataGridHierarchyRow` with `childRows` defined, otherwise `false`. */ -const isHierarchyGridRow = (row: GridRow): row is HierarchyGridRow & { childRows: HierarchyGridRow[] | GridRow[] } => +const isDataGridHierarchyRow = ( + row: DataGridRow +): row is DataGridHierarchyRow & { childRows: DataGridHierarchyRow[] | DataGridRow[] } => Array.isArray(row.childRows) && row.childRows.length > 0; /** * Renders a trigger for hierarchical row expansion in the grid. - * @param {HierarchyGridRow[]} rows - List of all hierarchy grid rows. - * @param {HierarchyGridRow} triggerRow - Row object with children that can be expanded or collapsed. + * @param {DataGridHierarchyRow[]} rows - List of all hierarchy grid rows. + * @param {DataGridHierarchyRow} triggerRow - Row object with children that can be expanded or collapsed. * @param {string} uniqueRowId - Unique identifier for each row. * @param {string} columnKey - Key of the column that displays the hierarchy trigger. * @param {Function} setRowsToRender - Function to update the rows being rendered. @@ -144,17 +149,17 @@ const isHierarchyGridRow = (row: GridRow): row is HierarchyGridRow & { childRows * @returns {JSX.Element} Button that toggles visibility of child rows. */ export const renderHierarchyTrigger = ( - rows: HierarchyGridRow[], - triggerRow: HierarchyGridRow, + rows: DataGridHierarchyRow[], + triggerRow: DataGridHierarchyRow, uniqueRowId: string, columnKey: string, - setRowsToRender: (_value: SetStateAction<GridRow[] | ExpandableGridRow[] | HierarchyGridRow[]>) => void, + setRowsToRender: (_value: SetStateAction<DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[]>) => void, loadingChildren?: (string | number)[], setLoadingChildren?: (_value: SetStateAction<(string | number)[]>) => void, childrenTrigger?: ( _open: boolean, - _selectedRow: HierarchyGridRow - ) => (HierarchyGridRow[] | GridRow[]) | Promise<HierarchyGridRow[] | GridRow[]> + _selectedRow: DataGridHierarchyRow + ) => (DataGridHierarchyRow[] | DataGridRow[]) | Promise<DataGridHierarchyRow[] | DataGridRow[]> ) => { const isLoading = !!loadingChildren?.includes(rowKeyGetter(triggerRow, uniqueRowId)); const expandChildren = async () => { @@ -172,7 +177,7 @@ export const renderHierarchyTrigger = ( const newRowsToRender = [...currentRows]; if (newRowsToRender.some((row) => rowKeyGetter(row, uniqueRowId) === triggerRow[uniqueRowId])) { const rowIndex = currentRows.findIndex((row) => triggerRow === row); - dynamicChildren.forEach((childRow: HierarchyGridRow, index: number) => { + dynamicChildren.forEach((childRow: DataGridHierarchyRow, index: number) => { childRow.rowLevel = triggerRow.rowLevel && typeof triggerRow.rowLevel === "number" ? triggerRow.rowLevel + 1 : 1; childRow.parentKey = rowKeyGetter(triggerRow, uniqueRowId); @@ -193,7 +198,7 @@ export const renderHierarchyTrigger = ( const newRowsToRender = [...currentRows]; const rowIndex = currentRows.findIndex((row) => triggerRow === row); - triggerRow.childRows?.forEach((childRow: HierarchyGridRow, index: number) => { + triggerRow.childRows?.forEach((childRow: DataGridHierarchyRow, index: number) => { childRow.rowLevel = triggerRow.rowLevel && typeof triggerRow.rowLevel === "number" ? triggerRow.rowLevel + 1 : 1; childRow.parentKey = rowKeyGetter(triggerRow, uniqueRowId); @@ -222,7 +227,7 @@ export const renderHierarchyTrigger = ( } else { setRowsToRender((currentRows) => { // The children of the row that is being collapsed are added to an array - const rowsToRemove: HierarchyGridRow[] = rows.filter( + const rowsToRemove: DataGridHierarchyRow[] = rows.filter( (rowToRender) => rowToRender.parentKey && rowToRender.parentKey === rowKeyGetter(triggerRow, uniqueRowId) ); // The children are checked if any of them has any other children of their own @@ -268,16 +273,16 @@ export const renderHierarchyTrigger = ( /** * Renders a checkbox for row selection. - * @param {GridRow[] | HierarchyGridRow[] | ExpandableGridRow[]} rows - Array of rows that are currently displayed. - * @param {GridRow | HierarchyGridRow | ExpandableGridRow} row - Row object to render the checkbox for. + * @param {DataGridRow | DataGridHierarchyRow | DataGridExpandableRow} row - Row object to render the checkbox for. + * @param {GridRow | DataGridHierarchyRow | DataGridExpandableRow} row - Row object to render the checkbox for. * @param {string} uniqueRowId - The key used to uniquely identify each row. * @param {Set<string | number>} selectedRows - Set of selected rows. * @param {Function} onSelectRows - Callback function that triggers when rows are selected/deselected. * @returns {JSX.Element} Checkbox for selecting the row. */ export const renderCheckbox = ( - rows: GridRow[] | HierarchyGridRow[] | ExpandableGridRow[], - row: GridRow | HierarchyGridRow | ExpandableGridRow, + rows: DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[], + row: DataGridRow | DataGridHierarchyRow | DataGridExpandableRow, uniqueRowId: string, selectedRows: Set<string | number>, onSelectRows: (_selected: Set<string | number>) => void @@ -301,14 +306,14 @@ export const renderCheckbox = ( /** * Renders a header checkbox that controls the selection of all rows. - * @param {GridRow[] | HierarchyGridRow[] | ExpandableGridRow[]} rows - Array of rows that are currently displayed. + * @param {DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[]} rows - Array of rows that are currently displayed. * @param {string} uniqueRowId - The key used to uniquely identify each row. * @param {Set<string | number>} selectedRows - Set of selected rows. * @param {Function} onSelectRows - Callback function that triggers when rows are selected/deselected. * @returns {JSX.Element} Checkbox for the header checkbox. */ export const renderHeaderCheckbox = ( - rows: GridRow[] | HierarchyGridRow[] | ExpandableGridRow[], + rows: DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[], uniqueRowId: string, selectedRows: Set<string | number>, onSelectRows: (_selected: Set<string | number>) => void @@ -321,14 +326,14 @@ export const renderHeaderCheckbox = ( if (checked) { rows.forEach((row) => { updatedSelection.add(rowKeyGetter(row, uniqueRowId)); - if (isHierarchyGridRow(row)) { + if (isDataGridHierarchyRow(row)) { getChildrenSelection(row.childRows, uniqueRowId, updatedSelection, checked); } }); } else { rows.forEach((row) => { updatedSelection.delete(rowKeyGetter(row, uniqueRowId)); - if (isHierarchyGridRow(row)) { + if (isDataGridHierarchyRow(row)) { getChildrenSelection(row.childRows, uniqueRowId, updatedSelection, checked); } }); @@ -342,21 +347,21 @@ export const renderHeaderCheckbox = ( /** * Retrieves the unique key for a row based on the given uniqueRowId. - * @param {GridRow | HierarchyGridRow | ExpandableGridRow} row - The row object from which to retrieve the key. + * @param {DataGridRow | DataGridHierarchyRow | DataGridExpandableRow} row - The row object from which to retrieve the key. * @param {string} uniqueRowId - The unique key used to identify the row. * @returns {string | number} The unique key of the row. */ -export const rowKeyGetter = (row: GridRow | HierarchyGridRow | ExpandableGridRow, uniqueRowId: string) => { +export const rowKeyGetter = (row: DataGridRow | DataGridHierarchyRow | DataGridExpandableRow, uniqueRowId: string) => { const keyValue = row[uniqueRowId]; return typeof keyValue === "string" || typeof keyValue === "number" ? keyValue : ""; }; /** * Extracts and returns custom sorting functions from the given columns. - * @param {GridColumn[]} columns - Array of column definitions. + * @param {DataGridColumn[]} columns - Array of column definitions. * @returns {object[]} Array of objects, each containing a column key and its custom sort function. */ -export const getCustomSortFn = (columns: GridColumn[]) => { +export const getCustomSortFn = (columns: DataGridColumn[]) => { const customSortFunctions = [...columns] .filter((column) => column.sortFn) .map((column) => ({ column: column.key, sortFn: column.sortFn! })); @@ -383,14 +388,14 @@ export const compareRows = (rowA: ReactNode, rowB: ReactNode, sortFn?: (_a: Reac /** * Sorts an array of rows based on the specified sort columns and custom sort functions. - * @param {GridRow[] | ExpandableGridRow[] | HierarchyGridRow[]} rows - Array of rows to be sorted. + * @param {DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[]} rows - Array of rows to be sorted. * @param {SortColumn[]} sortColumns - Array of sort column definitions. * @param {Function[]} sortFunctions - Array of objects, each containing a column and its custom sort function. * @param {boolean} reversed - Boolean indicating whether the sort order should be reversed. - * @returns {GridRow[] | ExpandableGridRow[] | HierarchyGridRow[]} The sorted array of rows. + * @returns {DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[]} The sorted array of rows. */ export const sortRows = ( - rows: GridRow[] | ExpandableGridRow[] | HierarchyGridRow[], + rows: DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[], sortColumns: readonly SortColumn[], sortFunctions?: { column: string; sortFn: (_a: ReactNode, _b: ReactNode) => number }[], reversed?: boolean @@ -425,14 +430,14 @@ export const sortRows = ( /** * Sorts an array of rows, ensuring child rows are placed under their parents. - * @param {HierarchyGridRow[]} rows - Array of rows to be sorted. + * @param {DataGridHierarchyRow[]} rows - Array of rows to be sorted. * @param {SortColumn[]} sortColumns - Array of sort column definitions. * @param {object[]} sortFunctions - Array of custom sort functions for specific columns. * @param {string} uniqueRowId - Unique key used to identify rows. - * @returns {GridRow[] | ExpandableGridRow[] | HierarchyGridRow[]} The sorted array of rows, with children positioned under their parents. + * @returns {DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[]} The sorted array of rows, with children positioned under their parents. */ export const sortHierarchyRows = ( - rows: HierarchyGridRow[], + rows: DataGridHierarchyRow[], sortColumns: readonly SortColumn[], sortFunctions: { column: string; sortFn: (_a: ReactNode, _b: ReactNode) => number }[], uniqueRowId: string @@ -457,8 +462,8 @@ export const sortHierarchyRows = ( if (uniqueRowId && sortedChildren.some((row) => uniqueRowId in row)) { sortedChildren = sortedChildren.reduce( ( - remainingChilds: GridRow[] | HierarchyGridRow[] | ExpandableGridRow[], - child: GridRow | HierarchyGridRow | ExpandableGridRow + remainingChilds: DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[], + child: DataGridRow | DataGridHierarchyRow | DataGridExpandableRow ) => { const parentIndex = parentsSorted.findIndex( (parent) => rowKeyGetter(parent, uniqueRowId) === child.parentKey @@ -479,39 +484,39 @@ export const sortHierarchyRows = ( /** * Inserts a new row into the row list at the specified index. - * @param {GridRow[] | HierarchyGridRow[] | ExpandableGridRow[]} rowList - Array of rows to insert the new row into. + * @param {DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[]} rowList - Array of rows to insert the new row into. * @param {number} index - Index where the new row should be added. - * @param {GridRow | HierarchyGridRow | ExpandableGridRow} row - The row to be added. + * @param {GridRow | DataGridHierarchyRow | DataGridExpandableRow} row - The row to be added. */ export const addRow = ( - rowList: GridRow[] | HierarchyGridRow[] | ExpandableGridRow[], + rowList: DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[], index: number, - row: GridRow | HierarchyGridRow | ExpandableGridRow + row: DataGridRow | DataGridHierarchyRow | DataGridExpandableRow ) => { rowList.splice(index, 0, row); }; /** * Deletes a row from the specified index of a list of rows. - * @param {GridRow[] | HierarchyGridRow[] | ExpandableGridRow[]} rowList - Array rows from which to delete a row. + * @param {DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[]} rowList - Array rows from which to delete a row. * @param {number} index - Index where the row should be deleted. */ -export const deleteRow = (rowList: GridRow[] | HierarchyGridRow[] | ExpandableGridRow[], index: number) => { +export const deleteRow = (rowList: DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[], index: number) => { rowList.splice(index, 1); }; /** - * @param {GridRow[] | HierarchyGridRow[] | ExpandableGridRow[]} rowList List of rows in which to look for the row, it will also look for the row in the childRows + * @param {DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[]} rowList List of rows in which to look for the row, it will also look for the row in the childRows * @param {string} uniqueRowId The key that contains the unique value of the row * @param {ReactNode} uniqueRowIdValue Unique value to identify the row - * @returns {GridRow | HierarchyGridRow | ExpandableGridRow | undefined} A copy of the Row or undefined if not found + * @returns {GridRow | DataGridHierarchyRow | DataGridExpandableRow | undefined} A copy of the Row or undefined if not found */ export const rowFinderBasedOnId = ( - rowList: GridRow[] | HierarchyGridRow[] | ExpandableGridRow[], + rowList: DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[], uniqueRowId: string, uniqueRowIdValue: ReactNode -): GridRow | HierarchyGridRow | ExpandableGridRow | undefined => { - let foundRow: GridRow | HierarchyGridRow | ExpandableGridRow | undefined; +): DataGridRow | DataGridHierarchyRow | DataGridExpandableRow | undefined => { + let foundRow: DataGridRow | DataGridHierarchyRow | DataGridExpandableRow | undefined; rowList.forEach((row) => { if (rowKeyGetter(row, uniqueRowId) === uniqueRowIdValue) { foundRow = { ...row }; @@ -527,21 +532,21 @@ export const rowFinderBasedOnId = ( /** * Recursively selects or deselects children rows based on the checked state. - * @param {GridRow[] | HierarchyGridRow[]} rowList - List of child rows that need to be checked/unchecked. + * @param {DataGridRow[] | DataGridHierarchyRow[]} rowList - List of child rows that need to be checked/unchecked. * @param {string} uniqueRowId - Key used to uniquely identify each row. * @param {Set<string | number>} selectedRows - Set of selected rows. * @param {boolean} checked - Boolean indicating whether the rows should be selected (true) or deselected (false). * @param {boolean} expandingChildren - Defines children are being expanded or not, used to avoid removing children that were previously set when expanding an unset parent */ const getChildrenSelection = ( - rowList: GridRow[] | HierarchyGridRow[], + rowList: DataGridRow[] | DataGridHierarchyRow[], uniqueRowId: string, selectedRows: Set<string | number>, checked: boolean, hierarchyValidation?: boolean ) => { rowList.forEach((row) => { - if (isHierarchyGridRow(row)) { + if (isDataGridHierarchyRow(row)) { // Recursively select/deselect child rows getChildrenSelection(row.childRows, uniqueRowId, selectedRows, checked, hierarchyValidation); } @@ -557,7 +562,7 @@ const getChildrenSelection = ( /** * Check if the parent and its parent should be selected/unselected - * @param {HierarchyGridRow[]} rowList + * @param {DataGridHierarchyRow[]} rowList * @param {ReactNode} uniqueRowKeyValue Unique value of the selected row * @param {ReactNode} parentKeyValue Unique value of the parent Row * @param {string} uniqueRowId Key where the unique value is located @@ -565,7 +570,7 @@ const getChildrenSelection = ( * @param {boolean} checkedStateToMatch */ const getParentSelectedState = ( - rowList: HierarchyGridRow[], + rowList: DataGridHierarchyRow[], parentKeyValue: ReactNode, uniqueRowId: string, selectedRows: Set<string | number>, @@ -574,9 +579,9 @@ const getParentSelectedState = ( if (!rowList.some((row) => uniqueRowId in row)) { return; } - const parentRow = rowFinderBasedOnId(rowList, uniqueRowId, parentKeyValue) as HierarchyGridRow; + const parentRow = rowFinderBasedOnId(rowList, uniqueRowId, parentKeyValue) as DataGridHierarchyRow; - if (!parentRow || !isHierarchyGridRow(parentRow)) { + if (!parentRow || !isDataGridHierarchyRow(parentRow)) { return; } @@ -601,8 +606,8 @@ const getParentSelectedState = ( /** * Updates the rows when the checkbox state changes - * @param {GridRow[] | HierarchyGridRow[] | ExpandableGridRow[]} rows - Array of rows that are currently displayed. - * @param {GridRow | HierarchyGridRow | ExpandableGridRow} row - Row object to render the checkbox for. + * @param {DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[]} rows - Array of rows that are currently displayed. + * @param {GridRow | DataGridHierarchyRow | DataGridExpandableRow} row - Row object to render the checkbox for. * @param {string} uniqueRowId - Unique identifier for each row. * @param {string} columnKey - Key of the column that displays the hierarchy trigger. * @param {Set<string | number>} selectedRows - Set of selected rows. @@ -611,8 +616,8 @@ const getParentSelectedState = ( * @returns {JSX.Element} Button that toggles visibility of child rows. */ const handleCheckboxUpdate = ( - rows: GridRow[] | HierarchyGridRow[] | ExpandableGridRow[], - row: GridRow | HierarchyGridRow | ExpandableGridRow, + rows: DataGridRow[] | DataGridHierarchyRow[] | DataGridExpandableRow[], + row: DataGridRow | DataGridHierarchyRow | DataGridExpandableRow, uniqueRowId: string, selectedRows: Set<string | number>, checked: boolean, @@ -648,35 +653,35 @@ export const getMinItemsPerPageIndex = (currentPageInternal: number, itemsPerPag * Returns the ending index for paginated items on a specific page. * @param {number} minItemsPerPageIndex - The starting index of items for the current page. * @param {number} itemsPerPage - Number of items per page. - * @param {GridRow[] | ExpandableGridRow[] | HierarchyGridRow[]} rows - List of all rows to paginate. + * @param {DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[]} rows - List of all rows to paginate. * @param {number} page - Target page number. * @returns {number} The ending index of items for the given page. */ export const getMaxItemsPerPageIndex = ( minItemsPerPageIndex: number, itemsPerPage: number, - rows: GridRow[] | ExpandableGridRow[] | HierarchyGridRow[], + rows: DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[], page: number ) => (minItemsPerPageIndex + itemsPerPage > rows.length ? rows.length : itemsPerPage * page - 1); /** * Filters and returns paginated rows along with their children rows if applicable. - * @param {GridRow[] | ExpandableGridRow[] | HierarchyGridRow[]} rows - All rows from which to select the paginated ones. + * @param {DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[]} rows - All rows from which to select the paginated ones. * @param {string} uniqueRowId - The key used to uniquely identify each row. * @param {number} start - The starting index for pagination. * @param {number} end - The ending index for pagination. - * @returns {GridRow[] | ExpandableGridRow[] | HierarchyGridRow[]} List of rows that should be rendered in the current pagination view, including child rows. + * @returns {DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[]} List of rows that should be rendered in the current pagination view, including child rows. */ export const getPaginatedNodes = ( - rows: readonly GridRow[] | ExpandableGridRow[] | HierarchyGridRow[], + rows: readonly DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[], uniqueRowId?: string, start?: number, end?: number -): readonly GridRow[] | ExpandableGridRow[] | HierarchyGridRow[] => { +): readonly DataGridRow[] | DataGridExpandableRow[] | DataGridHierarchyRow[] => { if (!uniqueRowId) { return rows.slice(start, end); } - const rowsToPaginate: HierarchyGridRow[] = + const rowsToPaginate: DataGridHierarchyRow[] = start != null && end != null ? rows .filter(({ parentKey, isExpandedChildContent }) => parentKey == null && isExpandedChildContent == null) @@ -684,7 +689,7 @@ export const getPaginatedNodes = ( : [...rows]; // Recursive function to check childRows at any depth - const isRowInHierarchy = (row: HierarchyGridRow, targetId: ReactNode): boolean => { + const isRowInHierarchy = (row: DataGridHierarchyRow, targetId: ReactNode): boolean => { if (row[uniqueRowId] === targetId) { return true; } @@ -696,10 +701,10 @@ export const getPaginatedNodes = ( rowsToPaginate.some( (rowToPaginate) => rowToPaginate[uniqueRowId] === row[uniqueRowId] || - (rowToPaginate.contentIsExpanded && + (rowToPaginate.contentIsExpanded === true && row?.triggerRowKey === rowToPaginate[uniqueRowId] && - row?.isExpandedChildContent) || - rowToPaginate?.childRows?.some((child) => isRowInHierarchy(child, row[uniqueRowId])) + row?.isExpandedChildContent === true) || + rowToPaginate.childRows?.some((child) => isRowInHierarchy(child, row[uniqueRowId])) ) ); }; @@ -714,4 +719,4 @@ export const getPaginatedNodes = ( * @returns {boolean} - Returns `true` if `key` is a valid key of `obj`, otherwise `false`. * */ -export const isKeyOfRow = <T extends GridRow>(key: string, obj: T): key is Extract<keyof T, string> => key in obj; +export const isKeyOfRow = <T extends DataGridRow>(key: string, obj: T): key is Extract<keyof T, string> => key in obj; diff --git a/packages/lib/src/date-input/DateInput.tsx b/packages/lib/src/date-input/DateInput.tsx index f471256993..b5bd0ca020 100644 --- a/packages/lib/src/date-input/DateInput.tsx +++ b/packages/lib/src/date-input/DateInput.tsx @@ -3,7 +3,7 @@ import dayjs, { Dayjs } from "dayjs"; import styled from "@emotion/styled"; import customParseFormat from "dayjs/plugin/customParseFormat"; import { HalstackLanguageContext } from "../HalstackContext"; -import DateInputPropsType from "./types"; +import { DateInputProps } from "./types"; import DatePicker from "./DatePicker"; import { getMargin } from "../common/utils"; import { spaces } from "../common/variables"; @@ -22,12 +22,12 @@ const sizes = { fillParent: "100%", }; -const calculateWidth = (margin: DateInputPropsType["margin"], size: DateInputPropsType["size"]) => +const calculateWidth = (margin: DateInputProps["margin"], size: DateInputProps["size"]) => size === "fillParent" ? `calc(${sizes[size]} - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})` : size && sizes[size]; -const DateInputContainer = styled.div<{ margin: DateInputPropsType["margin"]; size: DateInputPropsType["size"] }>` +const DateInputContainer = styled.div<{ margin: DateInputProps["margin"]; size: DateInputProps["size"] }>` ${(props) => props.size === "fillParent" && "width: 100%;"} display: flex; flex-direction: column; @@ -46,7 +46,7 @@ const DateInputContainer = styled.div<{ margin: DateInputPropsType["margin"]; si `; const Label = styled.label<{ - disabled: DateInputPropsType["disabled"]; + disabled: DateInputProps["disabled"]; hasHelperText: boolean; }>` color: ${(props) => (props.disabled ? "var(--color-fg-neutral-medium);" : "var(--color-fg-neutral-dark);")}; @@ -56,13 +56,13 @@ const Label = styled.label<{ `; const OptionalLabel = styled.span<{ - disabled: DateInputPropsType["disabled"]; + disabled: DateInputProps["disabled"]; }>` color: ${(props) => (props.disabled ? "var(--color-fg-neutral-medium);" : "var(--color-fg-neutral-stronger);")}; font-weight: var(--typography-label-regular); `; -const HelperText = styled.span<{ disabled: DateInputPropsType["disabled"] }>` +const HelperText = styled.span<{ disabled: DateInputProps["disabled"] }>` color: ${(props) => (props.disabled ? "var(--color-fg-neutral-medium);" : "var(--color-fg-neutral-stronger);")}; font-size: var(--typography-helper-text-s); font-weight: var(--typography-helper-text-regular); @@ -96,7 +96,7 @@ const DxcDateInput = ({ tabIndex, ariaLabel = "Date input", ref, -}: DateInputPropsType) => { +}: DateInputProps) => { const [innerValue, setInnerValue] = useState(defaultValue); const [isOpen, setIsOpen] = useState(false); const calendarId = `date-picker-${useId()}`; diff --git a/packages/lib/src/date-input/types.ts b/packages/lib/src/date-input/types.ts index 1f056cb6a2..ae8fcce98f 100644 --- a/packages/lib/src/date-input/types.ts +++ b/packages/lib/src/date-input/types.ts @@ -3,7 +3,7 @@ import { Margin, Space } from "../common/types"; export type RefType = React.Ref<HTMLDivElement>; -type Props = { +export type DateInputProps = { /** * Initial value of the input element, only when it is uncontrolled. */ @@ -184,4 +184,4 @@ export type DateUnitPickerPropsType = { unit?: "month" | "year"; }; -export default Props; +export type { DateInputProps as default }; diff --git a/packages/lib/src/dialog/types.ts b/packages/lib/src/dialog/types.ts index 558068c6e3..0fe1c784fd 100644 --- a/packages/lib/src/dialog/types.ts +++ b/packages/lib/src/dialog/types.ts @@ -1,6 +1,6 @@ import { ReactNode } from "react"; -type Props = { +export type DialogProps = { /** * If true, the close button will be visible. */ @@ -40,4 +40,4 @@ type Props = { disableFocusLock?: boolean; }; -export default Props; +export type { DialogProps as default }; diff --git a/packages/lib/src/divider/Divider.tsx b/packages/lib/src/divider/Divider.tsx index 17ee8757e9..88ab06edcf 100644 --- a/packages/lib/src/divider/Divider.tsx +++ b/packages/lib/src/divider/Divider.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; -import DividerPropsType from "./types"; +import { DividerProps } from "./types"; -const StyledDivider = styled.hr<DividerPropsType>` +const StyledDivider = styled.hr<DividerProps>` ${({ orientation, weight, color }) => ` border-color: ${ color === "lightGrey" @@ -26,7 +26,7 @@ export default function DxcDivider({ decorative = true, orientation = "horizontal", weight = "regular", -}: DividerPropsType) { +}: DividerProps) { return ( <StyledDivider aria-hidden={decorative} diff --git a/packages/lib/src/divider/types.ts b/packages/lib/src/divider/types.ts index 6c2bce91b6..64a0ccf5a2 100644 --- a/packages/lib/src/divider/types.ts +++ b/packages/lib/src/divider/types.ts @@ -1,4 +1,4 @@ -type Props = { +export type DividerProps = { /** * The divider can be shown in horizontal or vertical. */ @@ -19,4 +19,4 @@ type Props = { decorative?: boolean; }; -export default Props; +export type { DividerProps as default }; diff --git a/packages/lib/src/dropdown/Dropdown.tsx b/packages/lib/src/dropdown/Dropdown.tsx index 5537d2945e..afb9f68c91 100644 --- a/packages/lib/src/dropdown/Dropdown.tsx +++ b/packages/lib/src/dropdown/Dropdown.tsx @@ -5,7 +5,7 @@ import { spaces } from "../common/variables"; import DxcIcon from "../icon/Icon"; import useWidth from "../utils/useWidth"; import DropdownMenu from "./DropdownMenu"; -import DropdownPropsType from "./types"; +import { DropdownProps } from "./types"; import DxcPopover from "../popover/Popover"; import { Tooltip } from "../tooltip/Tooltip"; @@ -17,15 +17,15 @@ const sizes = { fitContent: "fit-content", }; -const calculateWidth = (margin: DropdownPropsType["margin"], size: DropdownPropsType["size"]) => +const calculateWidth = (margin: DropdownProps["margin"], size: DropdownProps["size"]) => size != null && (size === "fillParent" ? `calc(${sizes[size]} - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})` : sizes[size]); const DropdownContainer = styled.div<{ - margin: DropdownPropsType["margin"]; - size: DropdownPropsType["size"]; + margin: DropdownProps["margin"]; + size: DropdownProps["size"]; }>` width: ${(props) => calculateWidth(props.margin, props.size)}; margin: ${(props) => (props.margin && typeof props.margin !== "object" ? spaces[props.margin] : "0px")}; @@ -40,9 +40,9 @@ const DropdownContainer = styled.div<{ `; const DropdownTrigger = styled.button<{ - label: DropdownPropsType["label"]; - margin: DropdownPropsType["margin"]; - size: DropdownPropsType["size"]; + label: DropdownProps["label"]; + margin: DropdownProps["margin"]; + size: DropdownProps["size"]; }>` display: flex; justify-content: space-between; @@ -71,7 +71,7 @@ const DropdownTrigger = styled.button<{ `}; `; -const DropdownTriggerContent = styled.span<{ iconPosition: DropdownPropsType["iconPosition"] }>` +const DropdownTriggerContent = styled.span<{ iconPosition: DropdownProps["iconPosition"] }>` display: flex; ${({ iconPosition }) => (iconPosition === "after" ? "flex-direction: row-reverse;" : "flex-direction: row;")} align-items: center; @@ -90,7 +90,7 @@ const DropdownTriggerLabel = styled.span` `; const DropdownTriggerIcon = styled.span<{ - disabled: DropdownPropsType["disabled"]; + disabled: DropdownProps["disabled"]; }>` display: flex; font-size: var(--height-xs); @@ -101,7 +101,7 @@ const DropdownTriggerIcon = styled.span<{ } `; -const CaretIcon = styled.span<{ disabled: DropdownPropsType["disabled"] }>` +const CaretIcon = styled.span<{ disabled: DropdownProps["disabled"] }>` display: flex; font-size: var(--typography-label-l); @@ -134,7 +134,7 @@ const DxcDropdown = ({ size = "fitContent", tabIndex = 0, title, -}: DropdownPropsType) => { +}: DropdownProps) => { const id = useId(); const triggerId = `trigger-${id}`; const menuId = `menu-${id}`; diff --git a/packages/lib/src/dropdown/types.ts b/packages/lib/src/dropdown/types.ts index 8474892c13..889eed06a0 100644 --- a/packages/lib/src/dropdown/types.ts +++ b/packages/lib/src/dropdown/types.ts @@ -1,9 +1,7 @@ import { CSSProperties, KeyboardEvent } from "react"; import { Margin, SVG, Space } from "../common/types"; -type Size = "small" | "medium" | "large" | "fillParent" | "fitContent"; - -export type Option = { +export type DropdownOption = { /** * Option display value. */ @@ -22,11 +20,11 @@ export type Option = { hasDivider?: boolean; }; -type Props = { +export type DropdownProps = { /** * An array of objects representing the options. */ - options: Option[]; + options: DropdownOption[]; /** * In case options include icons, whether the icon should appear * after or before the label. @@ -70,7 +68,7 @@ type Props = { /** * Size of the component. */ - size?: Size; + size?: "small" | "medium" | "large" | "fillParent" | "fitContent"; /** * Value of the tabindex attribute. */ @@ -89,7 +87,7 @@ export type DropdownMenuProps = { visualFocusIndex: number; menuItemOnClick: (value: string) => void; onKeyDown: (event: KeyboardEvent<HTMLUListElement>) => void; - options: Option[]; + options: DropdownOption[]; ref: React.Ref<HTMLUListElement>; styles: CSSProperties; }; @@ -99,7 +97,7 @@ export type DropdownMenuItemProps = { visuallyFocused: boolean; iconPosition: "before" | "after"; onClick: (value: string) => void; - option: Option; + option: DropdownOption; }; -export default Props; +export type { DropdownProps as default }; diff --git a/packages/lib/src/file-input/FileInput.tsx b/packages/lib/src/file-input/FileInput.tsx index 92ed214386..50ac1caaf4 100644 --- a/packages/lib/src/file-input/FileInput.tsx +++ b/packages/lib/src/file-input/FileInput.tsx @@ -3,16 +3,16 @@ import styled from "@emotion/styled"; import DxcButton from "../button/Button"; import { spaces } from "../common/variables"; import FileItem from "./FileItem"; -import FileInputPropsType, { FileData } from "./types"; +import { FileInputProps, FileData } from "./types"; import { HalstackLanguageContext } from "../HalstackContext"; import { getFilePreview, isFileIncluded } from "./utils"; import HelperText from "../styles/forms/HelperText"; import Label from "../styles/forms/Label"; const FileInputContainer = styled.div<{ - margin: FileInputPropsType["margin"]; - mode: FileInputPropsType["mode"]; - size: FileInputPropsType["size"]; + margin: FileInputProps["margin"]; + mode: FileInputProps["mode"]; + size: FileInputProps["size"]; }>` display: flex; flex-direction: column; @@ -56,10 +56,10 @@ const Container = styled.div` `; const DragDropArea = styled.div<{ - mode: FileInputPropsType["mode"]; - disabled: FileInputPropsType["disabled"]; + mode: FileInputProps["mode"]; + disabled: FileInputProps["disabled"]; isDragging: boolean; - size: FileInputPropsType["size"]; + size: FileInputProps["size"]; }>` box-sizing: border-box; display: flex; @@ -84,7 +84,7 @@ const DragDropArea = styled.div<{ cursor: ${(props) => props.disabled && "not-allowed"}; `; -const DropzoneLabel = styled.div<{ disabled: FileInputPropsType["disabled"] }>` +const DropzoneLabel = styled.div<{ disabled: FileInputProps["disabled"] }>` display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; @@ -97,7 +97,7 @@ const DropzoneLabel = styled.div<{ disabled: FileInputPropsType["disabled"] }>` font-weight: var(--typography-helper-text-regular); `; -const FiledropLabel = styled.span<{ disabled: FileInputPropsType["disabled"] }>` +const FiledropLabel = styled.span<{ disabled: FileInputProps["disabled"] }>` overflow: hidden; white-space: nowrap; text-overflow: ellipsis; @@ -126,7 +126,7 @@ const DxcFileInput = ({ tabIndex = 0, optional = false, ref, -}: FileInputPropsType) => { +}: FileInputProps) => { const [isDragging, setIsDragging] = useState(false); const [files, setFiles] = useState<FileData[]>([]); const fileInputId = `file-input-${useId()}`; diff --git a/packages/lib/src/file-input/types.ts b/packages/lib/src/file-input/types.ts index 3bf58f28c9..82697635f2 100644 --- a/packages/lib/src/file-input/types.ts +++ b/packages/lib/src/file-input/types.ts @@ -1,4 +1,4 @@ -import { Margin, Space } from "../common/types"; +import { Margin, PrettifyTypes, Space } from "../common/types"; /** * Reference to the component. @@ -119,7 +119,7 @@ type FileModeProps = CommonProps & { mode?: "file"; }; -type Props = DropModeProps | FileModeProps; +export type FileInputProps = PrettifyTypes<DropModeProps | FileModeProps>; /** * Single file item preview. @@ -136,4 +136,4 @@ export type FileItemProps = { size: "medium" | "fillParent"; }; -export default Props; +export type { FileInputProps as default }; diff --git a/packages/lib/src/flex/Flex.tsx b/packages/lib/src/flex/Flex.tsx index ca57aa486a..42cf3dcb70 100644 --- a/packages/lib/src/flex/Flex.tsx +++ b/packages/lib/src/flex/Flex.tsx @@ -1,5 +1,5 @@ import styled from "@emotion/styled"; -import FlexPropsType, { StyledProps } from "./types"; +import type { FlexProps, StyledProps } from "./types"; const Flex = styled.div<StyledProps>` display: flex; @@ -20,7 +20,7 @@ const Flex = styled.div<StyledProps>` `} `; -const DxcFlex = ({ basis, direction, fullHeight = false, gap, grow, order, shrink, wrap, ...props }: FlexPropsType) => ( +const DxcFlex = ({ basis, direction, fullHeight = false, gap, grow, order, shrink, wrap, ...props }: FlexProps) => ( <Flex $basis={basis} $direction={direction} diff --git a/packages/lib/src/flex/types.ts b/packages/lib/src/flex/types.ts index b610975302..4b1a628d81 100644 --- a/packages/lib/src/flex/types.ts +++ b/packages/lib/src/flex/types.ts @@ -1,6 +1,7 @@ import { ReactNode } from "react"; +import { PrettifyTypes } from "../common/types"; -type Gap = { rowGap: string; columnGap?: string } | { rowGap?: string; columnGap: string } | string; +export type FlexGap = { rowGap: string; columnGap?: string } | { rowGap?: string; columnGap: string } | string; type CommonProps = { /** @@ -60,72 +61,76 @@ type CommonProps = { alignSelf?: "auto" | "flex-start" | "flex-end" | "center" | "baseline" | "stretch"; }; -type Props = CommonProps & { - /** - * Sets the flex-direction CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction - */ - direction?: "row" | "row-reverse" | "column" | "column-reverse"; - /** - * Sets the flex-wrap CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap - */ - wrap?: "nowrap" | "wrap" | "wrap-reverse"; - /** - * Sets the gap CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/gap - */ - gap?: Gap; - /** - * Sets the order CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/order - */ - order?: number; - /** - * If true, the flex container will take the full height of its parent. - */ - fullHeight?: boolean; - /** - * Sets the flex-grow CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow - */ - grow?: number; - /** - * Sets the flex-shrink CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-shrink - */ - shrink?: number; - /** - * Sets the flex-basis CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis - */ - basis?: string; - /** - * Sets a custom HTML tag. - */ - as?: keyof HTMLElementTagNameMap; - /** - * Custom content inside the flex container. - */ - children: ReactNode; -}; +export type FlexProps = PrettifyTypes< + CommonProps & { + /** + * Sets the flex-direction CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction + */ + direction?: "row" | "row-reverse" | "column" | "column-reverse"; + /** + * Sets the flex-wrap CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap + */ + wrap?: "nowrap" | "wrap" | "wrap-reverse"; + /** + * Sets the gap CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/gap + */ + gap?: FlexGap; + /** + * Sets the order CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/order + */ + order?: number; + /** + * If true, the flex container will take the full height of its parent. + */ + fullHeight?: boolean; + /** + * Sets the flex-grow CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow + */ + grow?: number; + /** + * Sets the flex-shrink CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-shrink + */ + shrink?: number; + /** + * Sets the flex-basis CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis + */ + basis?: string; + /** + * Sets a custom HTML tag. + */ + as?: keyof HTMLElementTagNameMap; + /** + * Custom content inside the flex container. + */ + children: ReactNode; + } +>; -export type StyledProps = CommonProps & { - $direction?: "row" | "row-reverse" | "column" | "column-reverse"; - $wrap?: "nowrap" | "wrap" | "wrap-reverse"; - $gap?: Gap; - $fullHeight?: boolean; - $order?: number; - $grow?: number; - $shrink?: number; - $basis?: string; -}; +export type StyledProps = PrettifyTypes< + CommonProps & { + $direction?: "row" | "row-reverse" | "column" | "column-reverse"; + $wrap?: "nowrap" | "wrap" | "wrap-reverse"; + $gap?: FlexGap; + $fullHeight?: boolean; + $order?: number; + $grow?: number; + $shrink?: number; + $basis?: string; + } +>; -export default Props; +export type { FlexProps as default }; diff --git a/packages/lib/src/footer/Footer.tsx b/packages/lib/src/footer/Footer.tsx index 0edd31c5bc..a23f8f963a 100644 --- a/packages/lib/src/footer/Footer.tsx +++ b/packages/lib/src/footer/Footer.tsx @@ -3,7 +3,7 @@ import styled from "@emotion/styled"; import DxcIcon from "../icon/Icon"; import { Tooltip } from "../tooltip/Tooltip"; import { dxcLogo, dxcSmallLogo } from "./Icons"; -import FooterPropsType from "./types"; +import { FooterProps } from "./types"; import { HalstackLanguageContext, HalstackLogosContext } from "../HalstackContext"; import { getContrastColor, getResponsiveStyles } from "./utils"; import DxcLink from "../link/Link"; @@ -11,7 +11,7 @@ import useWidth from "../utils/useWidth"; import { css } from "@emotion/react"; const FooterContainer = styled.footer<{ - mode?: FooterPropsType["mode"]; + mode?: FooterProps["mode"]; }>` box-sizing: border-box; display: flex; @@ -53,7 +53,7 @@ const LeftContainer = styled.div<{ width: number }>` `} `; -const LogoContainer = styled.span<{ mode?: FooterPropsType["mode"] }>` +const LogoContainer = styled.span<{ mode?: FooterProps["mode"] }>` max-height: ${(props) => (props?.mode === "default" ? "var(--height-xl)" : "var(--height-xxs)")}; width: fit-content; text-align: center; @@ -72,7 +72,7 @@ const LogoContainer = styled.span<{ mode?: FooterPropsType["mode"] }>` } `; -const LogoImg = styled.img<{ mode: FooterPropsType["mode"] }>` +const LogoImg = styled.img<{ mode: FooterProps["mode"] }>` max-height: ${(props) => (props.mode === "default" ? "var(--height-m)" : "var(--height-xxs)")}; width: auto; `; @@ -127,7 +127,7 @@ const SocialIconContainer = styled.div` } `; -const BottomContainer = styled.div<{ textColor: string; width: number; variant: FooterPropsType["variant"] }>` +const BottomContainer = styled.div<{ textColor: string; width: number; variant: FooterProps["variant"] }>` width: 100%; min-height: var(--height-xl); display: grid; @@ -216,7 +216,7 @@ const DxcFooter = ({ socialLinks, variant = "branded", tabIndex = 0, -}: FooterPropsType): JSX.Element => { +}: FooterProps): JSX.Element => { const translatedLabels = use(HalstackLanguageContext).labels; const themedLogos = use(HalstackLogosContext); diff --git a/packages/lib/src/footer/types.ts b/packages/lib/src/footer/types.ts index 37f74aa978..603a119349 100644 --- a/packages/lib/src/footer/types.ts +++ b/packages/lib/src/footer/types.ts @@ -1,7 +1,7 @@ import { ReactNode } from "react"; import { SVG } from "../common/types"; -type SocialLink = { +type FooterSocialLink = { /** * URL of the page the link goes to. */ @@ -16,7 +16,7 @@ type SocialLink = { title: string; }; -type BottomLink = { +type FooterBottomLink = { /** * URL of the page the link goes to. */ @@ -27,7 +27,7 @@ type BottomLink = { text: string; }; -type Logo = { +type FooterLogo = { /** * Source of the logo image. */ @@ -38,12 +38,12 @@ type Logo = { alt: string; }; -type FooterPropsType = { +type FooterProps = { /** * An array of objects representing the links that will be rendered at * the bottom part of the footer. */ - bottomLinks?: BottomLink[]; + bottomLinks?: FooterBottomLink[]; /** * The text that will be displayed as copyright disclaimer. */ @@ -55,7 +55,7 @@ type FooterPropsType = { /** * Logo to be displayed inside the footer */ - logo?: Logo; + logo?: FooterLogo; /** * Determines the visual style and layout * - "default": The default mode with full content and styling. @@ -70,7 +70,7 @@ type FooterPropsType = { * An array of objects representing the links that will be rendered as * icons at the top-right side of the footer. */ - socialLinks?: SocialLink[]; + socialLinks?: FooterSocialLink[]; /** * Value of the tabindex for all interactive elements, except those * inside the leftContent and rightContent. @@ -82,4 +82,4 @@ type FooterPropsType = { variant?: "branded" | "neutral"; }; -export default FooterPropsType; +export type { FooterProps as default, FooterProps, FooterBottomLink, FooterLogo, FooterSocialLink }; diff --git a/packages/lib/src/grid/Grid.tsx b/packages/lib/src/grid/Grid.tsx index 7e1797a76b..63ab25a42a 100644 --- a/packages/lib/src/grid/Grid.tsx +++ b/packages/lib/src/grid/Grid.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; -import GridPropsType, { GridItemProps } from "./types"; +import { GridProps, GridItemProps } from "./types"; -const Grid = styled.div<GridPropsType>` +const Grid = styled.div<GridProps>` display: grid; ${(props) => ` ${props.templateColumns ? `grid-template-columns: ${props.templateColumns.join(" ")};` : ""} @@ -91,7 +91,7 @@ const GridItem = styled.div<GridItemProps>` `} `; -const DxcGrid = (props: GridPropsType) => <Grid {...props} />; +const DxcGrid = (props: GridProps) => <Grid {...props} />; DxcGrid.Item = GridItem; export default DxcGrid; diff --git a/packages/lib/src/grid/types.ts b/packages/lib/src/grid/types.ts index 3bf02a22c0..c692c16e7c 100644 --- a/packages/lib/src/grid/types.ts +++ b/packages/lib/src/grid/types.ts @@ -1,19 +1,12 @@ import { ReactNode } from "react"; +import { PrettifyTypes } from "../common/types"; -type Gap = string | { columnGap?: string; rowGap: string } | { columnGap: string; rowGap?: string }; +type GridGap = string | { columnGap?: string; rowGap: string } | { columnGap: string; rowGap?: string }; type GridCell = { end: number | string; start: number | string }; -type PlaceSelfValues = "auto" | "baseline" | "center" | "end" | "start" | "stretch"; -type PlaceContentValues = - | "baseline" - | "center" - | "end" - | "normal" - | "space-around" - | "space-between" - | "space-evenly" - | "start" - | "stretch"; -type PlaceItemsValues = "baseline" | "center" | "end" | "normal" | "start" | "stretch"; +type GridPlaceSelfValues = "auto" | "baseline" | "center" | "end" | "start" | "stretch"; +type GridPlaceContentValues = + "baseline" | "center" | "end" | "normal" | "space-around" | "space-between" | "space-evenly" | "start" | "stretch"; +type GridPlaceItemsValues = "baseline" | "center" | "end" | "normal" | "start" | "stretch"; type PlaceObject<Type, Suffix extends string> = { [Property in Extract<keyof Type, string> as `${Property}${Capitalize<Suffix>}`]: Type[Property]; }; @@ -22,7 +15,7 @@ type PlaceGeneric<PlaceValues, Element extends string> = | PlaceObject<{ align?: PlaceValues; justify: PlaceValues }, Element> | PlaceValues; -export type GridItemProps = { +type GridItemProps = { /** * Sets the name of an item so that it can be referenced by a template created with the grid-template-areas property. */ @@ -46,7 +39,7 @@ export type GridItemProps = { * * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/place-self */ - placeSelf?: PlaceGeneric<PlaceSelfValues, "self">; + placeSelf?: PlaceGeneric<GridPlaceSelfValues, "self">; /** * Sets the grid-row CSS property. * @@ -55,61 +48,72 @@ export type GridItemProps = { row?: number | string | GridCell; }; -type Props = GridItemProps & { - /** - * Sets the grid-auto-columns CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-columns - */ - autoColumns?: string; - /** - * Sets the grid-auto-flow CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow - */ - autoFlow?: "row" | "column" | "row dense" | "column dense"; - /** - * Sets the grid-auto-rows CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows - */ - autoRows?: string; - /** - * Sets the gap CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/gap - */ - gap?: Gap; - /** - * Sets the place-content CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/place-content - */ - placeContent?: PlaceGeneric<PlaceContentValues, "content">; - /** - * Sets the place-items CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/place-items - */ - placeItems?: PlaceGeneric<PlaceItemsValues, "items">; - /** - * Sets the grid-template-areas CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas - */ - templateAreas?: string[]; - /** - * Sets the grid-template-columns CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns - */ - templateColumns?: string[]; - /** - * Sets the grid-template-rows CSS property. - * - * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows - */ - templateRows?: string[]; -}; +type GridProps = PrettifyTypes< + GridItemProps & { + /** + * Sets the grid-auto-columns CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-columns + */ + autoColumns?: string; + /** + * Sets the grid-auto-flow CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow + */ + autoFlow?: "row" | "column" | "row dense" | "column dense"; + /** + * Sets the grid-auto-rows CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows + */ + autoRows?: string; + /** + * Sets the gap CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/gap + */ + gap?: GridGap; + /** + * Sets the place-content CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/place-content + */ + placeContent?: PlaceGeneric<GridPlaceContentValues, "content">; + /** + * Sets the place-items CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/place-items + */ + placeItems?: PlaceGeneric<GridPlaceItemsValues, "items">; + /** + * Sets the grid-template-areas CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas + */ + templateAreas?: string[]; + /** + * Sets the grid-template-columns CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns + */ + templateColumns?: string[]; + /** + * Sets the grid-template-rows CSS property. + * + * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows + */ + templateRows?: string[]; + } +>; -export default Props; +export type { + GridProps as default, + GridProps, + GridCell, + GridItemProps, + GridGap, + GridPlaceSelfValues, + GridPlaceContentValues, + GridPlaceItemsValues, +}; diff --git a/packages/lib/src/heading/types.ts b/packages/lib/src/heading/types.ts index 5a12a363c4..b8a42fc1df 100644 --- a/packages/lib/src/heading/types.ts +++ b/packages/lib/src/heading/types.ts @@ -1,6 +1,6 @@ import { Margin, Space } from "../common/types"; -type Props = { +type HeadingProps = { /** * Defines the heading level from 1 to 5. The styles of the heading are applied according to the level. * The html tag of the heading will be the one specified in the 'as' prop. @@ -26,4 +26,4 @@ type Props = { margin?: Space | Margin; }; -export default Props; +export type { HeadingProps, HeadingProps as default }; diff --git a/packages/lib/src/heading/utils.ts b/packages/lib/src/heading/utils.ts index 02771a9e70..dd90a3429a 100644 --- a/packages/lib/src/heading/utils.ts +++ b/packages/lib/src/heading/utils.ts @@ -1,6 +1,6 @@ -import HeadingPropsType from "./types"; +import { HeadingProps } from "./types"; -export const getHeadingSize = (level: HeadingPropsType["level"]) => { +export const getHeadingSize = (level: HeadingProps["level"]) => { switch (level) { case 1: return "var(--typography-heading-xxl)"; @@ -17,7 +17,7 @@ export const getHeadingSize = (level: HeadingPropsType["level"]) => { } }; -export const getHeadingWeight = (weight: HeadingPropsType["weight"]) => { +export const getHeadingWeight = (weight: HeadingProps["weight"]) => { switch (weight) { case "default": return "var(--typography-heading-semibold)"; diff --git a/packages/lib/src/image/Image.tsx b/packages/lib/src/image/Image.tsx index 7ed3d15ac8..ca1b97f69c 100644 --- a/packages/lib/src/image/Image.tsx +++ b/packages/lib/src/image/Image.tsx @@ -1,6 +1,6 @@ import styled from "@emotion/styled"; import { ReactNode } from "react"; -import ImagePropsType from "./types"; +import { ImageProps } from "./types"; const Figure = styled.figure` display: flex; @@ -18,7 +18,7 @@ const CaptionContainer = styled.figcaption` font-weight: var(--typography-label-regular); `; -const CaptionWrapper = ({ caption, children }: { caption: ImagePropsType["caption"]; children: ReactNode }) => +const CaptionWrapper = ({ caption, children }: { caption: ImageProps["caption"]; children: ReactNode }) => caption != null ? ( <Figure> {children} @@ -41,7 +41,7 @@ export default function DxcImage({ src, srcSet, width, -}: ImagePropsType) { +}: ImageProps) { return ( <CaptionWrapper caption={caption}> <img diff --git a/packages/lib/src/image/types.ts b/packages/lib/src/image/types.ts index 15d741890f..9956ce6ab8 100644 --- a/packages/lib/src/image/types.ts +++ b/packages/lib/src/image/types.ts @@ -1,6 +1,6 @@ import { ReactEventHandler } from "react"; -type Props = { +type ImageProps = { /** * Alternative text description displayed when the specified image is not loaded. * @@ -66,4 +66,4 @@ type Props = { width?: string; }; -export default Props; +export type { ImageProps, ImageProps as default }; diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index 807a5d28b6..e96fc512e8 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -77,6 +77,7 @@ export type { export type { ApplicationLayoutProps as DxcAppLayoutProps, AppLayoutMainProps as DxcAppLayoutMainProps, + AppLayoutLogo as DxcAppLayoutLogo, } from "./layout/types"; export type { AvatarProps as DxcAvatarProps, AvatarStatus as DxcAvatarStatus } from "./avatar/types"; export type { BadgeProps as DxcBadgeProps } from "./badge/types"; @@ -103,12 +104,46 @@ export type { CardProps as DxcCardProps } from "./card/types"; export type { CheckboxProps as DxcCheckboxProps } from "./checkbox/types"; export type { ChipProps as DxcChipProps } from "./chip/types"; export type { ContextualMenuProps as DxcContextualMenuProps } from "./contextual-menu/types"; +export type { + DataGridProps as DxcDataGridProps, + DataGridRow as DxcDataGridRow, + DataGridHierarchyRow as DxcDataGridHierarchyRow, + DataGridExpandableRow as DxcDataGridExpandableRow, + DataGridExpandableRows as DxcDataGridExpandableRows, + DataGridHierarchyRows as DxcDataGridHierarchyRows, + DataGridSelectableProps as DxcDataGridSelectableProps, + DataGridBasicProps as DxcDataGridBasicProps, + DataGridColumn as DxcDataGridColumn, +} from "./data-grid/types"; +export type { DateInputProps as DxcDateInputProps } from "./date-input/types"; +export type { DialogProps as DxcDialogProps } from "./dialog/types"; +export type { DropdownProps as DxcDropdownProps, DropdownOption as DxcDropdownOption } from "./dropdown/types"; +export type { FileInputProps as DxcFileInputProps, FileData as DxcFileData } from "./file-input/types"; +export type { FlexProps as DxcFlexProps } from "./flex/types"; +export type { + FooterProps as DxcFooterProps, + FooterBottomLink as DxcFooterBottomLink, + FooterSocialLink as DxcFooterSocialLink, + FooterLogo as DxcFooterLogo, +} from "./footer/types"; +export type { + GridProps as DxcGridProps, + GridGap as DxcGridGap, + GridCell as DxcGridCell, + GridItemProps as DxcGridItemProps, + GridPlaceSelfValues as DxcGridPlaceSelfValues, + GridPlaceContentValues as DxcGridPlaceContentValues, + GridPlaceItemsValues as DxcGridPlaceItemsValues, +} from "./grid/types"; export type { HeaderProps as DxcHeaderProps, HeaderMainNavPropsType as DxcHeaderMainNavPropsType, HeaderSearchBarProps as DxcHeaderSearchBarProps, HeaderGroupItem as DxcHeaderGroupItem, } from "./header/types"; +export type { HeadingProps as DxcHeadingProps } from "./heading/types"; +export type { ImageProps as DxcImageProps } from "./image/types"; +export type { InsetProps as DxcInsetProps } from "./inset/types"; export type { SidenavProps as DxcSidenavProps, SidenavSection as DxcSidenavSection, diff --git a/packages/lib/src/inset/Inset.tsx b/packages/lib/src/inset/Inset.tsx index 9eb421db01..ad0ca0f9ea 100644 --- a/packages/lib/src/inset/Inset.tsx +++ b/packages/lib/src/inset/Inset.tsx @@ -1,7 +1,7 @@ -import InsetPropsType from "./types"; +import { InsetProps } from "./types"; import DxcContainer from "../container/Container"; -export default function DxcInset({ bottom, children, horizontal, left, right, space, top, vertical }: InsetPropsType) { +export default function DxcInset({ bottom, children, horizontal, left, right, space, top, vertical }: InsetProps) { return ( <DxcContainer padding={{ diff --git a/packages/lib/src/inset/types.ts b/packages/lib/src/inset/types.ts index af9833ef26..80075695c2 100644 --- a/packages/lib/src/inset/types.ts +++ b/packages/lib/src/inset/types.ts @@ -1,6 +1,6 @@ import { ReactNode } from "react"; -type Props = { +type InsetProps = { /** * Applies the spacing scale to the bottom side. */ @@ -35,4 +35,4 @@ type Props = { vertical?: string; }; -export default Props; +export type { InsetProps, InsetProps as default }; From 1ca669c1291e7f526dc302c14a759785ea616add Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Thu, 15 Oct 2026 17:09:14 +0200 Subject: [PATCH 08/18] Export types up to Radio component --- packages/lib/src/index.ts | 7 +++ .../src/layout/ApplicationLayoutContext.tsx | 4 +- packages/lib/src/layout/types.ts | 10 ++-- packages/lib/src/layout/utils.tsx | 4 +- packages/lib/src/link/types.ts | 2 + .../lib/src/message-input/MessageInput.tsx | 6 +-- packages/lib/src/message-input/types.ts | 4 +- packages/lib/src/nav-tabs/NavTabs.tsx | 4 +- packages/lib/src/nav-tabs/Tab.tsx | 14 ++--- packages/lib/src/nav-tabs/types.ts | 6 +-- .../src/navigation-tree/NavigationTree.tsx | 8 +-- packages/lib/src/navigation-tree/types.ts | 53 ++++++++++--------- packages/lib/src/number-input/NumberInput.tsx | 6 +-- packages/lib/src/number-input/types.ts | 12 ++--- packages/lib/src/paginator/types.ts | 4 +- .../lib/src/password-input/PasswordInput.tsx | 6 +-- packages/lib/src/password-input/types.ts | 4 +- packages/lib/src/popover/Popover.tsx | 4 +- packages/lib/src/popover/types.ts | 4 +- packages/lib/src/progress-bar/ProgressBar.tsx | 24 ++++----- packages/lib/src/progress-bar/types.ts | 4 +- packages/lib/src/quick-nav/QuickNav.tsx | 4 +- packages/lib/src/quick-nav/types.ts | 10 ++-- packages/lib/src/radio-group/RadioGroup.tsx | 6 +-- packages/lib/src/radio-group/types.ts | 8 +-- 25 files changed, 115 insertions(+), 103 deletions(-) diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index e96fc512e8..ac103aaba4 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -77,6 +77,7 @@ export type { export type { ApplicationLayoutProps as DxcAppLayoutProps, AppLayoutMainProps as DxcAppLayoutMainProps, + AppLayoutSidenavProps as DxcAppLayoutSidenavProps, AppLayoutLogo as DxcAppLayoutLogo, } from "./layout/types"; export type { AvatarProps as DxcAvatarProps, AvatarStatus as DxcAvatarStatus } from "./avatar/types"; @@ -144,6 +145,12 @@ export type { export type { HeadingProps as DxcHeadingProps } from "./heading/types"; export type { ImageProps as DxcImageProps } from "./image/types"; export type { InsetProps as DxcInsetProps } from "./inset/types"; +export type { LinkProps as DxcLinkProps } from "./link/types"; +export type { MessageInputProps as DxcMessageInputProps } from "./message-input/types"; +export type { NavTabsProps as DxcNavTabsProps, NavTabsTabProps as DxcNavTabsTabProps } from "./nav-tabs/types"; +export type { NumberInputProps as DxcNumberInputProps } from "./number-input/types"; +export type { PaginatorProps as DxcPaginatorProps } from "./paginator/types"; +export type { PasswordProps as DxcPasswordInputProps } from "./password-input/types"; export type { SidenavProps as DxcSidenavProps, SidenavSection as DxcSidenavSection, diff --git a/packages/lib/src/layout/ApplicationLayoutContext.tsx b/packages/lib/src/layout/ApplicationLayoutContext.tsx index 2da55fbd92..31d051932f 100644 --- a/packages/lib/src/layout/ApplicationLayoutContext.tsx +++ b/packages/lib/src/layout/ApplicationLayoutContext.tsx @@ -1,7 +1,7 @@ import { createContext } from "react"; -import { ApplicationLayoutContextType } from "./types"; +import { ApplicationLayoutContext } from "./types"; -export default createContext<ApplicationLayoutContextType>({ +export default createContext<ApplicationLayoutContext>({ logo: undefined, headerExists: false, setHideMainContent: () => {}, diff --git a/packages/lib/src/layout/types.ts b/packages/lib/src/layout/types.ts index 9c36e9bd34..cc9523a464 100644 --- a/packages/lib/src/layout/types.ts +++ b/packages/lib/src/layout/types.ts @@ -8,7 +8,7 @@ export type AppLayoutMainProps = { children: ReactNode; }; -type LogoPropsType = { +export type AppLayoutLogo = { /** * Alternative text for the logo image. */ @@ -27,7 +27,7 @@ type LogoPropsType = { src: string | SVG; }; -export type AppLayoutSidenavPropsType = { +export type AppLayoutSidenavProps = { /** * The area inside the sidenav. This area can be used to render the content inside the sidenav. */ @@ -38,11 +38,11 @@ export type AppLayoutSidenavPropsType = { title?: ReactNode; }; -export type ApplicationLayoutContextType = { +export type ApplicationLayoutContext = { /** * Logo properties. */ - logo?: LogoPropsType; + logo?: AppLayoutLogo; /** * Indicates if the header exists. */ @@ -57,7 +57,7 @@ export type ApplicationLayoutProps = { /** * Logo properties. */ - logo?: LogoPropsType; + logo?: AppLayoutLogo; /** * Header content. */ diff --git a/packages/lib/src/layout/utils.tsx b/packages/lib/src/layout/utils.tsx index 7f785f7c26..0ff8a87bf4 100644 --- a/packages/lib/src/layout/utils.tsx +++ b/packages/lib/src/layout/utils.tsx @@ -1,6 +1,6 @@ import { Children, isValidElement, useState, useEffect, ElementType } from "react"; import layoutIcons from "./Icons"; -import ApplicationLayoutPropsType from "./types"; +import { ApplicationLayoutProps } from "./types"; export const year = new Date().getFullYear(); @@ -37,7 +37,7 @@ export const socialLinks = [ }, ]; -export const findChildType = (children: ApplicationLayoutPropsType["children"], childType: ElementType) => +export const findChildType = (children: ApplicationLayoutProps["children"], childType: ElementType) => Children.toArray(children).find((child) => isValidElement(child) && child.type === childType); export const useResponsive = (breakpoint: string) => { diff --git a/packages/lib/src/link/types.ts b/packages/lib/src/link/types.ts index 6e2442518e..8ba8046241 100644 --- a/packages/lib/src/link/types.ts +++ b/packages/lib/src/link/types.ts @@ -48,3 +48,5 @@ export type LinkProps = { */ tabIndex?: number; }; + +export type { LinkProps as default }; diff --git a/packages/lib/src/message-input/MessageInput.tsx b/packages/lib/src/message-input/MessageInput.tsx index 4439d1c291..6d91494c31 100644 --- a/packages/lib/src/message-input/MessageInput.tsx +++ b/packages/lib/src/message-input/MessageInput.tsx @@ -1,7 +1,7 @@ import { ChangeEvent, FocusEvent, KeyboardEvent, MouseEvent, use, useEffect, useId, useRef, useState } from "react"; import styled from "@emotion/styled"; import scrollbarStyles from "../styles/scroll"; -import PromptInputPropsType from "./types"; +import { MessageInputProps } from "./types"; import { getFilePreview, getSelectedOption, inputStylesByStatePromptInput } from "./utils"; import DxcButton from "../button/Button"; import DxcChip from "../chip/Chip"; @@ -23,7 +23,7 @@ const sizes = { } as const; const MessageInput = styled.div<{ - disabled: Required<PromptInputPropsType>["disabled"]; + disabled: Required<MessageInputProps>["disabled"]; error: boolean; focus: boolean; hasFiles?: boolean; @@ -132,7 +132,7 @@ const DxcMessageInput = ({ size = "medium", tabIndex, value, -}: PromptInputPropsType) => { +}: MessageInputProps) => { const languageContext = use(HalstackLanguageContext); const translatedLabels = languageContext.labels; const locale = languageContext.locale ?? "en-US"; diff --git a/packages/lib/src/message-input/types.ts b/packages/lib/src/message-input/types.ts index a6a49969bf..7ae9db1d01 100644 --- a/packages/lib/src/message-input/types.ts +++ b/packages/lib/src/message-input/types.ts @@ -5,7 +5,7 @@ export type SelectOption = { selected?: boolean; }; -type Props = { +export type MessageInputProps = { /** * If true, the voice recording button will be shown. */ @@ -106,4 +106,4 @@ type Props = { value?: string; }; -export default Props; +export type { MessageInputProps as default }; diff --git a/packages/lib/src/nav-tabs/NavTabs.tsx b/packages/lib/src/nav-tabs/NavTabs.tsx index 00a823c740..227b6b1112 100644 --- a/packages/lib/src/nav-tabs/NavTabs.tsx +++ b/packages/lib/src/nav-tabs/NavTabs.tsx @@ -1,6 +1,6 @@ import { JSX, Children, KeyboardEvent, useMemo, useState } from "react"; import styled from "@emotion/styled"; -import NavTabsPropsType from "./types"; +import { NavTabsProps } from "./types"; import Tab from "./Tab"; import NavTabsContext from "./NavTabsContext"; import { getLabelFromTab, getPropInChild, getPreviousTabIndex, getNextTabIndex } from "./utils"; @@ -20,7 +20,7 @@ const Underline = styled.div` width: 100%; `; -const DxcNavTabs = ({ iconPosition = "left", tabIndex = 0, children }: NavTabsPropsType): JSX.Element => { +const DxcNavTabs = ({ iconPosition = "left", tabIndex = 0, children }: NavTabsProps): JSX.Element => { const [innerFocusIndex, setInnerFocusIndex] = useState<number | null>(null); const childArray = Children.toArray(children).filter((child) => typeof child === "object" && "props" in child); diff --git a/packages/lib/src/nav-tabs/Tab.tsx b/packages/lib/src/nav-tabs/Tab.tsx index ac4f76b96e..b33fb1261c 100644 --- a/packages/lib/src/nav-tabs/Tab.tsx +++ b/packages/lib/src/nav-tabs/Tab.tsx @@ -2,7 +2,7 @@ import { useEffect, use, useRef, useImperativeHandle, KeyboardEvent } from "reac import styled from "@emotion/styled"; import DxcBadge from "../badge/Badge"; import DxcFlex from "../flex/Flex"; -import NavTabsPropsType, { TabProps } from "./types"; +import { NavTabsProps, NavTabsTabProps } from "./types"; import NavTabsContext from "./NavTabsContext"; import DxcIcon from "../icon/Icon"; import DxcInset from "../inset/Inset"; @@ -15,8 +15,8 @@ const TabContainer = styled.div` const TabLink = styled.div< { - disabled: TabProps["disabled"]; - iconPosition: NavTabsPropsType["iconPosition"]; + disabled: NavTabsTabProps["disabled"]; + iconPosition: NavTabsProps["iconPosition"]; } & React.AnchorHTMLAttributes<HTMLAnchorElement> >` box-sizing: border-box; @@ -51,7 +51,7 @@ const TabLink = styled.div< `; const Label = styled.span<{ - disabled: TabProps["disabled"]; + disabled: NavTabsTabProps["disabled"]; }>` display: inline; color: ${({ disabled }) => (disabled ? "var(--color-fg-neutral-medium)" : "var(--color-fg-neutral-stronger)")}; @@ -65,7 +65,7 @@ const Label = styled.span<{ `; const IconContainer = styled.div<{ - disabled: TabProps["disabled"]; + disabled: NavTabsTabProps["disabled"]; }>` display: flex; color: ${({ disabled }) => (disabled ? "var(--color-fg-neutral-medium)" : "var(--color-fg-neutral-stronger)")}; @@ -76,7 +76,7 @@ const IconContainer = styled.div<{ } `; -const Underline = styled.span<{ active: TabProps["active"] }>` +const Underline = styled.span<{ active: NavTabsTabProps["active"] }>` position: absolute; left: 0; bottom: 0; @@ -96,7 +96,7 @@ const Tab = ({ onClick, ref, ...otherProps -}: TabProps) => { +}: NavTabsTabProps) => { const { iconPosition, tabIndex, focusedLabel } = use(NavTabsContext) ?? {}; const tabRef = useRef<HTMLAnchorElement | HTMLDivElement | null>(null); const innerRef = useRef<HTMLAnchorElement | HTMLDivElement | null>(null); diff --git a/packages/lib/src/nav-tabs/types.ts b/packages/lib/src/nav-tabs/types.ts index 53a8a7a780..a80a305f9d 100644 --- a/packages/lib/src/nav-tabs/types.ts +++ b/packages/lib/src/nav-tabs/types.ts @@ -7,7 +7,7 @@ export type NavTabsContextProps = { tabIndex: number; }; -export type TabProps = { +type NavTabsTabProps = { /** * Whether the tab is active or not. */ @@ -46,7 +46,7 @@ export type TabProps = { ref?: React.Ref<HTMLAnchorElement | HTMLDivElement>; }; -type Props = { +type NavTabsProps = { /** * Contains one or more DxcNavTabs.Tab. */ @@ -61,4 +61,4 @@ type Props = { tabIndex?: number; }; -export default Props; +export type { NavTabsProps as default, NavTabsProps, NavTabsTabProps }; diff --git a/packages/lib/src/navigation-tree/NavigationTree.tsx b/packages/lib/src/navigation-tree/NavigationTree.tsx index 9af732ae3d..b04be61180 100644 --- a/packages/lib/src/navigation-tree/NavigationTree.tsx +++ b/packages/lib/src/navigation-tree/NavigationTree.tsx @@ -1,7 +1,7 @@ import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"; import styled from "@emotion/styled"; import MenuItem from "../base-menu/MenuItem"; -import NavigationTreePropsType, { GroupItemWithId, ItemWithId, SectionWithId } from "./types"; +import NavigationTreeProps, { BaseGroupItemWithId, BaseItemWithId, BaseSectionWithId } from "./types"; import Section from "../base-menu/Section"; import NavigationTreeContext from "../base-menu/BaseMenuContext"; import scrollbarStyles from "../styles/scroll"; @@ -35,7 +35,7 @@ export default function DxcNavigationTree({ hasPopOver = false, isHorizontal = false, onSelectItem, -}: NavigationTreePropsType) { +}: NavigationTreeProps) { const [firstUpdate, setFirstUpdate] = useState(true); const [selectedItemId, setSelectedItemId] = useState(-1); const NavigationTreeRef = useRef<HTMLDivElement | null>(null); @@ -78,12 +78,12 @@ export default function DxcNavigationTree({ <NavigationTreeContainer displayBorder={displayBorder} ref={NavigationTreeRef}> <NavigationTreeContext value={contextValue}> {itemsWithId[0] && isSection(itemsWithId[0]) ? ( - (itemsWithId as SectionWithId[]).map((item, index) => ( + (itemsWithId as BaseSectionWithId[]).map((item, index) => ( <Section key={`section-${index}`} section={item} index={index} length={itemsWithId.length} /> )) ) : ( <SubMenu isHorizontal={isHorizontal}> - {(itemsWithId as (GroupItemWithId | ItemWithId)[]).map((item, index) => ( + {(itemsWithId as (BaseGroupItemWithId | BaseItemWithId)[]).map((item, index) => ( <MenuItem item={item} key={`${item.label}-${index}`} /> ))} </SubMenu> diff --git a/packages/lib/src/navigation-tree/types.ts b/packages/lib/src/navigation-tree/types.ts index 9afb437531..495723f820 100644 --- a/packages/lib/src/navigation-tree/types.ts +++ b/packages/lib/src/navigation-tree/types.ts @@ -1,32 +1,33 @@ -import Props, { +import { + BaseMenuProps, BaseMenuContextProps as NavigationTreeContextProps, - GroupItem, - GroupItemProps, - GroupItemWithId, - Item, - ItemActionProps, - ItemWithId, - SubMenuProps, - MenuItemProps, - Section, - SectionWithId, - SectionProps, - SingleItemProps, + BaseGroupItem, + BaseGroupItemProps, + BaseGroupItemWithId, + BaseItem, + BaseItemActionProps, + BaseItemWithId, + BaseSubMenuProps, + BaseMenuItemProps, + BaseSection, + BaseSectionWithId, + BaseSectionProps, + BaseSingleItemProps, } from "../base-menu/types"; export type { - GroupItem, - GroupItemProps, - GroupItemWithId, - Item, - ItemActionProps, - ItemWithId, - SubMenuProps, - MenuItemProps, + BaseGroupItem, + BaseGroupItemProps, + BaseGroupItemWithId, + BaseItem, + BaseItemActionProps, + BaseItemWithId, + BaseSubMenuProps, + BaseMenuItemProps, NavigationTreeContextProps, - Section, - SectionWithId, - SectionProps, - SingleItemProps, - Props as default, + BaseSection, + BaseSectionWithId, + BaseSectionProps, + BaseSingleItemProps, + BaseMenuProps as default, }; diff --git a/packages/lib/src/number-input/NumberInput.tsx b/packages/lib/src/number-input/NumberInput.tsx index 1ee3d71990..d636e4f551 100644 --- a/packages/lib/src/number-input/NumberInput.tsx +++ b/packages/lib/src/number-input/NumberInput.tsx @@ -1,10 +1,10 @@ import { useEffect, useMemo, useRef } from "react"; import styled from "@emotion/styled"; import DxcTextInput from "../text-input/TextInput"; -import NumberInputPropsType from "./types"; +import { NumberInputProps } from "./types"; import NumberInputContext from "./NumberInputContext"; -const NumberInputContainer = styled.div<{ size: NumberInputPropsType["size"] }>` +const NumberInputContainer = styled.div<{ size: NumberInputProps["size"] }>` ${({ size }) => size === "fillParent" && "width: 100%;"} // Chrome, Safari, Edge, Opera @@ -45,7 +45,7 @@ const DxcNumberInput = ({ suffix, tabIndex, value, -}: NumberInputPropsType) => { +}: NumberInputProps) => { const numberInputRef = useRef<HTMLInputElement | null>(null); const contextValue = useMemo( diff --git a/packages/lib/src/number-input/types.ts b/packages/lib/src/number-input/types.ts index 9bf33e5889..8aad68e49d 100644 --- a/packages/lib/src/number-input/types.ts +++ b/packages/lib/src/number-input/types.ts @@ -5,7 +5,7 @@ import { Margin, Space } from "../common/types"; */ export type RefType = React.Ref<HTMLInputElement>; -type Props = { +export type NumberInputProps = { /** * Text to be placed above the number. */ @@ -131,11 +131,11 @@ type Props = { }; export type NumberInputContextProps = { - maxNumber: Props["max"]; - minNumber: Props["min"]; - showControls: Props["showControls"]; - stepNumber: Props["step"]; + maxNumber: NumberInputProps["max"]; + minNumber: NumberInputProps["min"]; + showControls: NumberInputProps["showControls"]; + stepNumber: NumberInputProps["step"]; typeNumber?: string; }; -export default Props; +export type { NumberInputProps as default }; diff --git a/packages/lib/src/paginator/types.ts b/packages/lib/src/paginator/types.ts index d213d66c44..3f64b3b6e5 100644 --- a/packages/lib/src/paginator/types.ts +++ b/packages/lib/src/paginator/types.ts @@ -1,4 +1,4 @@ -type Props = { +export type PaginatorProps = { /** * Number of the current selected page. */ @@ -36,4 +36,4 @@ type Props = { tabIndex?: number; }; -export default Props; +export type { PaginatorProps as default }; diff --git a/packages/lib/src/password-input/PasswordInput.tsx b/packages/lib/src/password-input/PasswordInput.tsx index d3d156d38e..e2becd2f04 100644 --- a/packages/lib/src/password-input/PasswordInput.tsx +++ b/packages/lib/src/password-input/PasswordInput.tsx @@ -1,11 +1,11 @@ import { use, useLayoutEffect, useRef, useState } from "react"; import styled from "@emotion/styled"; import DxcTextInput from "../text-input/TextInput"; -import PasswordInputPropsType from "./types"; +import { PasswordInputProps } from "./types"; import { HalstackLanguageContext } from "../HalstackContext"; const PasswordInput = styled.div<{ - size: PasswordInputPropsType["size"]; + size: PasswordInputProps["size"]; isPasswordVisible: boolean; }>` ${(props) => props.size === "fillParent" && "width: 100%;"} @@ -35,7 +35,7 @@ const DxcPasswordInput = ({ tabIndex = 0, ariaLabel = "Password input", ref, -}: PasswordInputPropsType) => { +}: PasswordInputProps) => { const [isPasswordVisible, setIsPasswordVisible] = useState(false); const containerRef = useRef<HTMLInputElement | null>(null); const { passwordInput } = use(HalstackLanguageContext).labels; diff --git a/packages/lib/src/password-input/types.ts b/packages/lib/src/password-input/types.ts index b9257995dd..edb97ad309 100644 --- a/packages/lib/src/password-input/types.ts +++ b/packages/lib/src/password-input/types.ts @@ -5,7 +5,7 @@ import { Margin, Space } from "../common/types"; */ export type RefType = React.Ref<HTMLDivElement>; -type Props = { +export type PasswordInputProps = { /** * Specifies a string to be used as the name for the password input element when no `label` is provided. */ @@ -107,4 +107,4 @@ type Props = { value?: string; }; -export default Props; +export type { PasswordInputProps as default }; diff --git a/packages/lib/src/popover/Popover.tsx b/packages/lib/src/popover/Popover.tsx index 464c7537b5..ec97dae980 100644 --- a/packages/lib/src/popover/Popover.tsx +++ b/packages/lib/src/popover/Popover.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; import { JSX, useEffect, useId, useRef, useState } from "react"; import * as Popover from "@radix-ui/react-popover"; -import { PopoverPropsType } from "./types"; +import { PopoverProps } from "./types"; const PopoverWrapper = styled.div` width: fit-content; @@ -44,7 +44,7 @@ const DxcPopover = ({ onCloseAutoFocus, popoverContent, side = "bottom", -}: PopoverPropsType): JSX.Element => { +}: PopoverProps): JSX.Element => { const popOverId = `popover-${useId()}`; const isControlled = useRef(isOpen !== undefined); diff --git a/packages/lib/src/popover/types.ts b/packages/lib/src/popover/types.ts index 999ae1ed85..20a2385cdc 100644 --- a/packages/lib/src/popover/types.ts +++ b/packages/lib/src/popover/types.ts @@ -1,4 +1,4 @@ -export type PopoverPropsType = { +export type PopoverProps = { /** Action that triggers the popover to open. */ actionToOpen?: "click" | "hover"; /** Alignment of the popover relative to the trigger element. */ @@ -29,3 +29,5 @@ export type PopoverPropsType = { /** Side of the trigger where the popover will appear. */ side?: "top" | "bottom" | "left" | "right"; }; + +export type { PopoverProps as default }; diff --git a/packages/lib/src/progress-bar/ProgressBar.tsx b/packages/lib/src/progress-bar/ProgressBar.tsx index 0af5b55c31..8b987dec74 100644 --- a/packages/lib/src/progress-bar/ProgressBar.tsx +++ b/packages/lib/src/progress-bar/ProgressBar.tsx @@ -1,12 +1,12 @@ import { JSX, useEffect, useId, useState } from "react"; import styled from "@emotion/styled"; import { spaces } from "../common/variables"; -import ProgressBarPropsType from "./types"; +import { ProgressBarProps } from "./types"; import DxcFlex from "../flex/Flex"; import { auxTextStyles, labelTextStyles, textColorStyles } from "./utils"; const ProgressBarContainer = styled.div<{ - overlay: ProgressBarPropsType["overlay"]; + overlay: ProgressBarProps["overlay"]; }>` display: flex; flex-wrap: wrap; @@ -33,8 +33,8 @@ const Overlay = styled.div` `; const MainContainer = styled.div<{ - overlay: ProgressBarPropsType["overlay"]; - margin: ProgressBarPropsType["margin"]; + overlay: ProgressBarProps["overlay"]; + margin: ProgressBarProps["margin"]; }>` width: ${(props) => (props.overlay ? "80%" : "100%")}; margin: ${(props) => (props.margin && typeof props.margin !== "object" ? spaces[props.margin] : "0px")}; @@ -53,7 +53,7 @@ const MainContainer = styled.div<{ `; const ProgressBarLabel = styled.div<{ - overlay: ProgressBarPropsType["overlay"]; + overlay: ProgressBarProps["overlay"]; }>` ${labelTextStyles}; ${(props) => textColorStyles(props.overlay)}; @@ -64,21 +64,21 @@ const ProgressBarLabel = styled.div<{ `; const ProgressBarProgress = styled.div<{ - overlay: ProgressBarPropsType["overlay"]; + overlay: ProgressBarProps["overlay"]; }>` ${auxTextStyles}; ${(props) => textColorStyles(props.overlay)}; flex-shrink: 0; `; -const HelperText = styled.span<{ overlay: ProgressBarPropsType["overlay"] }>` +const HelperText = styled.span<{ overlay: ProgressBarProps["overlay"] }>` ${(props) => textColorStyles(props.overlay)}; ${auxTextStyles}; `; const LinearProgress = styled.div<{ - helperText: ProgressBarPropsType["helperText"]; - overlay: ProgressBarPropsType["overlay"]; + helperText: ProgressBarProps["helperText"]; + overlay: ProgressBarProps["overlay"]; }>` position: relative; border-radius: var(--border-radius-m); @@ -88,9 +88,9 @@ const LinearProgress = styled.div<{ `; const LinearProgressBar = styled.span<{ - overlay: ProgressBarPropsType["overlay"]; + overlay: ProgressBarProps["overlay"]; variant: "determinate" | "indeterminate"; - value: ProgressBarPropsType["value"]; + value: ProgressBarProps["value"]; }>` position: absolute; top: 0; @@ -145,7 +145,7 @@ const DxcProgressBar = ({ showValue, margin, ariaLabel = "Progress bar", -}: ProgressBarPropsType): JSX.Element => { +}: ProgressBarProps): JSX.Element => { const labelId = `label-${useId()}`; const [innerValue, setInnerValue] = useState<number | undefined>(); diff --git a/packages/lib/src/progress-bar/types.ts b/packages/lib/src/progress-bar/types.ts index c73cb0e8c0..0faea7c855 100644 --- a/packages/lib/src/progress-bar/types.ts +++ b/packages/lib/src/progress-bar/types.ts @@ -1,6 +1,6 @@ import { Margin, Space } from "../common/types"; -type Props = { +export type ProgressBarProps = { /** * Text to be placed above the progress bar. */ @@ -34,4 +34,4 @@ type Props = { ariaLabel?: string; }; -export default Props; +export type { ProgressBarProps as default }; diff --git a/packages/lib/src/quick-nav/QuickNav.tsx b/packages/lib/src/quick-nav/QuickNav.tsx index 5e322e1cad..3184c1f0b2 100644 --- a/packages/lib/src/quick-nav/QuickNav.tsx +++ b/packages/lib/src/quick-nav/QuickNav.tsx @@ -3,7 +3,7 @@ import slugify from "slugify"; import styled from "@emotion/styled"; import DxcHeading from "../heading/Heading"; import { HalstackLanguageContext } from "../HalstackContext"; -import QuickNavTypes from "./types"; +import { QuickNavProps } from "./types"; const QuickNavContainer = styled.div` display: flex; @@ -59,7 +59,7 @@ const Link = styled.a` } `; -export default function DxcQuickNav({ links, title }: QuickNavTypes) { +export default function DxcQuickNav({ links, title }: QuickNavProps) { const translatedLabels = use(HalstackLanguageContext).labels; const isHashRouter = (): boolean => { if (typeof window === "undefined") return false; diff --git a/packages/lib/src/quick-nav/types.ts b/packages/lib/src/quick-nav/types.ts index a6c061dc46..5dec437cbf 100644 --- a/packages/lib/src/quick-nav/types.ts +++ b/packages/lib/src/quick-nav/types.ts @@ -1,4 +1,4 @@ -type Link = { +export type QuickNavLink = { /** * Label to be shown in the link. */ @@ -6,10 +6,10 @@ type Link = { /** * Sublinks of the link. */ - links?: Link[]; + links?: QuickNavLink[]; }; -type Props = { +export type QuickNavProps = { /** * Title of the quick nav component. */ @@ -17,7 +17,7 @@ type Props = { /** * Links to be shown inside the quick nav component. */ - links: Link[]; + links: QuickNavLink[]; }; -export default Props; +export type { QuickNavProps as default }; diff --git a/packages/lib/src/radio-group/RadioGroup.tsx b/packages/lib/src/radio-group/RadioGroup.tsx index 5be76345bd..671cb0a712 100644 --- a/packages/lib/src/radio-group/RadioGroup.tsx +++ b/packages/lib/src/radio-group/RadioGroup.tsx @@ -2,7 +2,7 @@ import { FocusEvent, KeyboardEvent, useCallback, use, useId, useMemo, useState } import styled from "@emotion/styled"; import { HalstackLanguageContext } from "../HalstackContext"; import RadioInput from "./RadioInput"; -import RadioGroupPropsType from "./types"; +import { RadioGroupProps } from "./types"; import Label from "../styles/forms/Label"; import HelperText from "../styles/forms/HelperText"; import ErrorMessage from "../styles/forms/ErrorMessage"; @@ -13,7 +13,7 @@ const RadioGroupContainer = styled.div` flex-direction: column; `; -const RadioGroup = styled.div<{ stacking: RadioGroupPropsType["stacking"] }>` +const RadioGroup = styled.div<{ stacking: RadioGroupProps["stacking"] }>` display: flex; flex-wrap: wrap; flex-direction: ${({ stacking }) => stacking}; @@ -39,7 +39,7 @@ const DxcRadioGroup = ({ stacking = "column", tabIndex = 0, value, -}: RadioGroupPropsType) => { +}: RadioGroupProps) => { const id = `radio-group-${useId()}`; const labelId = `label-${id}`; const errorId = `error-${id}`; diff --git a/packages/lib/src/radio-group/types.ts b/packages/lib/src/radio-group/types.ts index 4a262d9262..894c5e319e 100644 --- a/packages/lib/src/radio-group/types.ts +++ b/packages/lib/src/radio-group/types.ts @@ -3,7 +3,7 @@ */ export type RefType = React.Ref<HTMLDivElement>; -type Option = { +type RadioGroupOption = { /** * Label of the option placed next to the radio input. */ @@ -20,7 +20,7 @@ type Option = { disabled?: boolean; }; -type RadioGroupProps = { +export type RadioGroupProps = { /** * Specifies a string to be used as the name for the radio group when no `label` is provided. */ @@ -70,7 +70,7 @@ type RadioGroupProps = { /** * An array of objects representing the selectable options. */ - options: Option[]; + options: RadioGroupOption[]; /** * This function will be called when the radio group loses the focus. An * object including the value and the error will be passed to this @@ -120,4 +120,4 @@ export type RadioInputProps = { tabIndex: number; }; -export default RadioGroupProps; +export type { RadioGroupProps as default }; From 5ca4ba574608f94228e9b7cfa28173e470e7ab53 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Mon, 19 Oct 2026 11:10:15 +0200 Subject: [PATCH 09/18] Export types up to toast --- packages/lib/src/action-icon/types.ts | 6 +- packages/lib/src/avatar/types.ts | 6 +- packages/lib/src/common/types.ts | 18 +++++ packages/lib/src/index.ts | 32 ++++++++- packages/lib/src/radio-group/types.ts | 2 +- .../src/resultset-table/ResultsetTable.tsx | 10 +-- packages/lib/src/resultset-table/types.ts | 18 +++-- packages/lib/src/resultset-table/utils.ts | 12 ++-- packages/lib/src/search-bar/types.ts | 2 + packages/lib/src/select/ListOption.tsx | 18 ++--- packages/lib/src/select/Listbox.tsx | 6 +- packages/lib/src/select/Select.tsx | 22 +++---- packages/lib/src/select/types.ts | 32 ++++----- packages/lib/src/select/utils.ts | 48 +++++++------- packages/lib/src/slider/Slider.tsx | 26 ++++---- packages/lib/src/slider/types.ts | 4 +- packages/lib/src/slider/utils.ts | 4 +- packages/lib/src/spinner/Spinner.tsx | 20 +++--- packages/lib/src/spinner/types.ts | 4 +- packages/lib/src/status-light/StatusLight.tsx | 18 ++--- packages/lib/src/status-light/types.ts | 9 ++- packages/lib/src/switch/Switch.tsx | 24 +++---- packages/lib/src/switch/types.ts | 4 +- packages/lib/src/table/Table.tsx | 12 ++-- packages/lib/src/table/types.ts | 40 +++++------ packages/lib/src/table/utils.ts | 4 +- packages/lib/src/tabs/Tab.tsx | 4 +- packages/lib/src/tabs/Tabs.stories.tsx | 2 +- packages/lib/src/tabs/Tabs.tsx | 10 +-- packages/lib/src/tabs/types.ts | 18 ++--- packages/lib/src/text-input/TextInput.tsx | 16 ++--- packages/lib/src/text-input/types.ts | 23 +------ packages/lib/src/text-input/utils.ts | 12 ++-- packages/lib/src/textarea/types.ts | 4 +- packages/lib/src/time-input/TimeInput.tsx | 10 +-- packages/lib/src/time-input/TimePicker.tsx | 4 +- .../lib/src/time-input/TimeSpinButton.tsx | 4 +- packages/lib/src/time-input/types.ts | 8 +-- packages/lib/src/toast/Toast.tsx | 17 ++--- packages/lib/src/toast/ToastContext.tsx | 4 +- packages/lib/src/toast/ToastIcon.tsx | 4 +- packages/lib/src/toast/ToastsQueue.tsx | 4 +- packages/lib/src/toast/types.ts | 66 +++++++++++-------- packages/lib/src/toast/utils.ts | 4 +- 44 files changed, 324 insertions(+), 291 deletions(-) diff --git a/packages/lib/src/action-icon/types.ts b/packages/lib/src/action-icon/types.ts index 9430e25b51..1506af6559 100644 --- a/packages/lib/src/action-icon/types.ts +++ b/packages/lib/src/action-icon/types.ts @@ -1,9 +1,9 @@ import { MouseEvent, ReactNode, Ref } from "react"; -import { SVG, Color, Shape, Size } from "../common/types"; +import { SVG, Color, Shape, Size, Mode } from "../common/types"; export type RefType = HTMLDivElement; export interface Status { - mode: "default" | "info" | "success" | "warning" | "error"; + mode: Mode; position: "top" | "bottom"; } @@ -54,4 +54,4 @@ export type ActionIconProps = | (CommonProps & { content: ReactNode; icon?: string | SVG }) | (CommonProps & { content?: ReactNode; icon: string | SVG }); -export type { ActionIconProps as default }; \ No newline at end of file +export type { ActionIconProps as default }; diff --git a/packages/lib/src/avatar/types.ts b/packages/lib/src/avatar/types.ts index 1c7d9692d2..8a11752ed7 100644 --- a/packages/lib/src/avatar/types.ts +++ b/packages/lib/src/avatar/types.ts @@ -1,8 +1,8 @@ import { Ref } from "react"; -import { SVG, Color, Size, Shape } from "../common/types"; +import { SVG, Color, Size, Shape, Mode } from "../common/types"; export type AvatarStatus = { - mode: "default" | "info" | "success" | "warning" | "error"; + mode: Mode; position: "top" | "bottom"; }; @@ -95,4 +95,4 @@ export type ContentType = { status?: AvatarStatus; }; -export type { AvatarProps as default }; \ No newline at end of file +export type { AvatarProps as default }; diff --git a/packages/lib/src/common/types.ts b/packages/lib/src/common/types.ts index 4b56377f5b..bb9f37b48f 100644 --- a/packages/lib/src/common/types.ts +++ b/packages/lib/src/common/types.ts @@ -13,6 +13,24 @@ export type Side = keyof Margin; export type Size = "xsmall" | "small" | "medium" | "large" | "xlarge" | "xxlarge"; export type Shape = "circle" | "square"; export type Color = "primary" | "secondary" | "tertiary" | "success" | "info" | "neutral" | "warning" | "error"; +export type Mode = "default" | "info" | "success" | "warning" | "error"; + +export type Action = { + /** + * This function will be called when the user clicks the action. + */ + onClick: () => void; + /** + * Icon to be placed in the action.. + */ + icon: string | SVG; + /** + * Text representing advisory information related + * to the button's action. Under the hood, this prop also serves + * as an accessible label for the component. + */ + title?: string; +}; /** * Utility type to make complex types more readable in TypeScript. diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index ac103aaba4..02e899ff87 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -58,6 +58,7 @@ export { default as useToast } from "./toast/useToast"; // types exports export type { + Action as DxcAction, Space as DxcSpace, Margin as DxcMargin, SVG as DxcSVG, @@ -150,9 +151,38 @@ export type { MessageInputProps as DxcMessageInputProps } from "./message-input/ export type { NavTabsProps as DxcNavTabsProps, NavTabsTabProps as DxcNavTabsTabProps } from "./nav-tabs/types"; export type { NumberInputProps as DxcNumberInputProps } from "./number-input/types"; export type { PaginatorProps as DxcPaginatorProps } from "./paginator/types"; -export type { PasswordProps as DxcPasswordInputProps } from "./password-input/types"; +export type { PasswordInputProps as DxcPasswordInputProps } from "./password-input/types"; +export type { + RadioGroupProps as DxcRadioGroupProps, + RadioGroupOption as DxcRadioGroupOption, +} from "./radio-group/types"; +export type { + ResultSetTableProps as DxcResultSetTableProps, + ResultSetTableColumn as DxcResultSetTableColumn, + ResultSetTableRow as DxcResultSetTableRow, +} from "./resultset-table/types"; +export type { + SelectProps as DxcSelectProps, + SelectOption as DxcSelectOption, + SelectOptionGroup as DxcSelectOptionGroup, +} from "./select/types"; export type { SidenavProps as DxcSidenavProps, SidenavSection as DxcSidenavSection, SidenavSearchbarProps as DxcSidenavSearchbarProps, } from "./sidenav/types"; +export type { SliderProps as DxcSliderProps } from "./slider/types"; +export type { SpinnerProps as DxcSpinnerProps } from "./spinner/types"; +export type { StatusLightProps as DxcStatusLightProps } from "./status-light/types"; +export type { SwitchProps as DxcSwitchProps } from "./switch/types"; +export type { TableProps as DxcTableProps, ActionsCellProps as DxcActionsCellProps } from "./table/types"; +export type { TabsProps as DxcTabsProps, TabsTabProps as DxcTabsTabProps } from "./tabs/types"; +export type { TextInputProps as DxcTextInputProps } from "./text-input/types"; +export type { TextAreaProps as DxcTextareaProps } from "./textarea/types"; +export type { + DefaultToast as DxcDefaultToast, + LoadingToast as DxcLoadingToast, + SemanticToast as DxcSemanticToast, + ToastsQueueProps as DxcToastsQueueProps, + ToastProps as DxcToastProps, +} from "./toast/types"; diff --git a/packages/lib/src/radio-group/types.ts b/packages/lib/src/radio-group/types.ts index 894c5e319e..486ce4d5bc 100644 --- a/packages/lib/src/radio-group/types.ts +++ b/packages/lib/src/radio-group/types.ts @@ -3,7 +3,7 @@ */ export type RefType = React.Ref<HTMLDivElement>; -type RadioGroupOption = { +export type RadioGroupOption = { /** * Label of the option placed next to the radio input. */ diff --git a/packages/lib/src/resultset-table/ResultsetTable.tsx b/packages/lib/src/resultset-table/ResultsetTable.tsx index a493f8281b..406cadeae1 100644 --- a/packages/lib/src/resultset-table/ResultsetTable.tsx +++ b/packages/lib/src/resultset-table/ResultsetTable.tsx @@ -2,15 +2,15 @@ import { useEffect, useMemo, useRef, useState, ComponentProps, HTMLAttributes, T import styled from "@emotion/styled"; import DxcPaginator from "../paginator/Paginator"; import DxcTable, { DxcActionsCell } from "../table/Table"; -import ResultsetTablePropsType, { Column, Row } from "./types"; +import { ResultSetTableProps, ResultSetTableColumn, ResultSetTableRow } from "./types"; import { assignIdsToRows, getMinItemsPerPageIndex, getMaxItemsPerPageIndex, sortArray } from "./utils"; import DxcIcon from "../icon/Icon"; import { TableVirtuoso } from "react-virtuoso"; import { Table, TableContainer } from "../styles/tables/tablesStyles"; const SortingHeader = styled.span<{ - isSortable: Column["isSortable"]; - mode: ResultsetTablePropsType["mode"]; + isSortable: ResultSetTableColumn["isSortable"]; + mode: ResultSetTableProps["mode"]; }>` display: flex; align-items: center; @@ -43,7 +43,7 @@ const DxcResultsetTable = ({ showGoToPage = true, tabIndex = 0, virtualizedHeight, -}: ResultsetTablePropsType) => { +}: ResultSetTableProps) => { const [page, setPage] = useState(1); const [sortColumnIndex, changeSortColumnIndex] = useState(-1); const [sortOrder, changeSortOrder] = useState<"ascending" | "descending">("ascending"); @@ -146,7 +146,7 @@ const DxcResultsetTable = ({ TableRow: (props: HTMLAttributes<HTMLTableRowElement>) => <tr {...props} />, }} fixedHeaderContent={renderHeaderRow} - itemContent={(_index: number, row: { id: string; cells: Row }) => ( + itemContent={(_index: number, row: { id: string; cells: ResultSetTableRow }) => ( <> {row.cells.map((cellContent, cellIndex) => ( <td key={`resultSetTableCellContent_${cellIndex}`}>{cellContent.displayValue}</td> diff --git a/packages/lib/src/resultset-table/types.ts b/packages/lib/src/resultset-table/types.ts index 0f02252b97..018321d9af 100644 --- a/packages/lib/src/resultset-table/types.ts +++ b/packages/lib/src/resultset-table/types.ts @@ -1,7 +1,7 @@ import { ReactNode } from "react"; -import { Margin, Space } from "../common/types"; +import { Margin, PrettifyTypes, Space } from "../common/types"; -export type Column = { +export type ResultSetTableColumn = { /** * Column display value. */ @@ -12,7 +12,7 @@ export type Column = { isSortable?: boolean; }; -type Cell = { +export type ResultSetTableRow = { /** * Value to be displayed in the cell. */ @@ -22,15 +22,13 @@ type Cell = { * column. If not indicated displayValue will be used for sorting. */ sortValue?: string | number | Date; -}; - -export type Row = Cell[]; +}[]; type CommonProps = { /** * An array of objects representing the columns of the table. */ - columns: Column[]; + columns: ResultSetTableColumn[]; /** * Size of the margin to be applied to the component. You can pass an object with 'top', * 'bottom', 'left' and 'right' properties in order to specify different margin sizes. @@ -46,7 +44,7 @@ type CommonProps = { * An array of objects representing the rows of the table, you will have * as many objects as columns in the table. */ - rows: Row[]; + rows: ResultSetTableRow[]; /** * Value of the tabindex attribute applied to the sortable icon. */ @@ -103,6 +101,6 @@ type NonPaginatedProps = CommonProps & { showGoToPage?: never; }; -type Props = PaginatedProps | NonPaginatedProps; +export type ResultSetTableProps = PrettifyTypes<PaginatedProps | NonPaginatedProps>; -export default Props; +export type { ResultSetTableProps as default }; diff --git a/packages/lib/src/resultset-table/utils.ts b/packages/lib/src/resultset-table/utils.ts index 86c9acd666..9b693e1545 100644 --- a/packages/lib/src/resultset-table/utils.ts +++ b/packages/lib/src/resultset-table/utils.ts @@ -1,7 +1,7 @@ import { ReactNode } from "react"; -import { Row } from "./types"; +import { ResultSetTableRow } from "./types"; -export const assignIdsToRows = (resultset: Row[]) => +export const assignIdsToRows = (resultset: ResultSetTableRow[]) => resultset.length > 0 ? resultset.map((row, index) => ({ cells: row, @@ -15,7 +15,7 @@ export const getMinItemsPerPageIndex = (currentPageInternal: number, itemsPerPag export const getMaxItemsPerPageIndex = ( minItemsPerPageIndex: number, itemsPerPage: number, - resultset: Row[], + resultset: ResultSetTableRow[], page: number ) => (minItemsPerPageIndex + itemsPerPage > resultset.length ? resultset.length : itemsPerPage * page - 1); @@ -24,7 +24,11 @@ export const isDateType = (value: ReactNode | Date): boolean => value instanceof export const normalizeSortValue = (sortValue: string | Date | ReactNode) => typeof sortValue === "string" ? sortValue.toUpperCase() : sortValue; -export const sortArray = (index: number, order: "ascending" | "descending", resultset: { id: string; cells: Row }[]) => +export const sortArray = ( + index: number, + order: "ascending" | "descending", + resultset: { id: string; cells: ResultSetTableRow }[] +) => resultset.slice().sort((element1, element2) => { const sortValueA = normalizeSortValue(element1.cells[index]?.sortValue || element1.cells[index]?.displayValue); const sortValueB = normalizeSortValue(element2.cells[index]?.sortValue || element2.cells[index]?.displayValue); diff --git a/packages/lib/src/search-bar/types.ts b/packages/lib/src/search-bar/types.ts index 5d67a8f39f..3cb71b0a04 100644 --- a/packages/lib/src/search-bar/types.ts +++ b/packages/lib/src/search-bar/types.ts @@ -34,3 +34,5 @@ export type SearchBarProps = { */ placeholder?: string; }; + +export type { SearchBarProps as default }; diff --git a/packages/lib/src/select/ListOption.tsx b/packages/lib/src/select/ListOption.tsx index c5015cd8a8..68969e0993 100644 --- a/packages/lib/src/select/ListOption.tsx +++ b/packages/lib/src/select/ListOption.tsx @@ -1,13 +1,13 @@ import { MouseEvent, useEffect, useRef, useState } from "react"; import styled from "@emotion/styled"; -import { OptionProps } from "./types"; +import { ListboxOptionProps } from "./types"; import DxcCheckbox from "../checkbox/Checkbox"; import DxcIcon from "../icon/Icon"; import { TooltipWrapper } from "../tooltip/Tooltip"; const OptionItem = styled.li<{ - visualFocused: OptionProps["visualFocused"]; - selected: OptionProps["isSelected"]; + visualFocused: ListboxOptionProps["visualFocused"]; + selected: ListboxOptionProps["isSelected"]; }>` list-style: none; padding: var(--spacing-padding-none) var(--spacing-padding-xs); @@ -24,10 +24,10 @@ const OptionItem = styled.li<{ `; const StyledOption = styled.span<{ - grouped: OptionProps["isGroupedOption"]; - last: OptionProps["isLastOption"]; - selected: OptionProps["isSelected"]; - visualFocused: OptionProps["visualFocused"]; + grouped: ListboxOptionProps["isGroupedOption"]; + last: ListboxOptionProps["isLastOption"]; + selected: ListboxOptionProps["isSelected"]; + visualFocused: ListboxOptionProps["visualFocused"]; }>` box-sizing: border-box; display: flex; @@ -66,7 +66,7 @@ const OptionContent = styled.span` } `; -const OptionLabel = styled.span<{ isSelectAllOption: OptionProps["isSelectAllOption"] }>` +const OptionLabel = styled.span<{ isSelectAllOption: ListboxOptionProps["isSelectAllOption"] }>` ${({ isSelectAllOption }) => isSelectAllOption && "font-weight: var(--typography-label-semibold);"} overflow: hidden; text-overflow: ellipsis; @@ -83,7 +83,7 @@ const ListOption = ({ onClick, option, visualFocused, -}: OptionProps) => { +}: ListboxOptionProps) => { const [hasTooltip, setHasTooltip] = useState(false); const checkboxRef = useRef<HTMLDivElement>(null); diff --git a/packages/lib/src/select/Listbox.tsx b/packages/lib/src/select/Listbox.tsx index 8fc3fc833f..bcd34766eb 100644 --- a/packages/lib/src/select/Listbox.tsx +++ b/packages/lib/src/select/Listbox.tsx @@ -5,7 +5,7 @@ import { HalstackLanguageContext } from "../HalstackContext"; import ListOption from "./ListOption"; import { getGroupSelectionType, groupsHaveOptions } from "./utils"; import scrollbarStyles from "../styles/scroll"; -import { FlattenedItem, ListboxProps, ListOptionGroupType, ListOptionType } from "./types"; +import { FlattenedItem, ListboxProps, SelectOptionGroup, SelectOption } from "./types"; import CheckboxContext from "../checkbox/CheckboxContext"; import { Virtuoso, VirtuosoHandle } from "react-virtuoso"; import DxcBleed from "../bleed/Bleed"; @@ -291,7 +291,7 @@ const NonVirtualizedListbox = ({ const listboxRef = useRef<HTMLDivElement>(null); let globalMappingIndex = (multiple ? enableSelectAll : optional) ? 0 : -1; - const getGroupOption = (groupId: string, option: ListOptionGroupType) => { + const getGroupOption = (groupId: string, option: SelectOptionGroup) => { if (multiple && enableSelectAll) { const groupSelectionType = getGroupSelectionType(option.options, currentValue as string[]); globalMappingIndex++; @@ -322,7 +322,7 @@ const NonVirtualizedListbox = ({ ); }; - const mapOptionFunc = (option: ListOptionType | ListOptionGroupType, mapIndex: number) => { + const mapOptionFunc = (option: SelectOption | SelectOptionGroup, mapIndex: number) => { if ("options" in option) { const groupId = `${id}-group-${mapIndex}`; diff --git a/packages/lib/src/select/Select.tsx b/packages/lib/src/select/Select.tsx index 6c75eb4c29..856cf3ae91 100644 --- a/packages/lib/src/select/Select.tsx +++ b/packages/lib/src/select/Select.tsx @@ -32,7 +32,7 @@ import { getGroupSelectionType, computeNewValue, } from "./utils"; -import SelectPropsType, { ListOptionGroupType, ListOptionType } from "./types"; +import type { SelectProps, SelectOptionGroup, SelectOption } from "./types"; import DxcActionIcon from "../action-icon/ActionIcon"; import DxcFlex from "../flex/Flex"; import ErrorMessage from "../styles/forms/ErrorMessage"; @@ -42,8 +42,8 @@ import inputStylesByState from "../styles/forms/inputStylesByState"; import DxcPopover from "../popover/Popover"; const SelectContainer = styled.div<{ - margin: SelectPropsType["margin"]; - size: SelectPropsType["size"]; + margin: SelectProps["margin"]; + size: SelectProps["size"]; }>` box-sizing: border-box; display: flex; @@ -62,7 +62,7 @@ const SelectContainer = styled.div<{ `; const Select = styled.div<{ - disabled: Required<SelectPropsType>["disabled"]; + disabled: Required<SelectProps>["disabled"]; error: boolean; }>` position: relative; @@ -81,7 +81,7 @@ const Select = styled.div<{ } `; -const SelectionIndicator = styled.div<{ disabled: SelectPropsType["disabled"] }>` +const SelectionIndicator = styled.div<{ disabled: SelectProps["disabled"] }>` display: grid; grid-template-columns: 1fr 1fr; min-width: 48px; @@ -91,7 +91,7 @@ const SelectionIndicator = styled.div<{ disabled: SelectPropsType["disabled"] }> ${({ disabled }) => (disabled ? "var(--border-color-neutral-strong)" : "var(--border-color-neutral-light)")}; `; -const SelectionNumber = styled.span<{ disabled: SelectPropsType["disabled"] }>` +const SelectionNumber = styled.span<{ disabled: SelectProps["disabled"] }>` display: grid; place-items: center; background-color: ${({ disabled }) => (disabled ? "transparent" : "var(--color-bg-neutral-lighter)")}; @@ -138,7 +138,7 @@ const SearchableValueContainer = styled.div` `; const SelectedOption = styled.span<{ - disabled: SelectPropsType["disabled"]; + disabled: SelectProps["disabled"]; atBackground: boolean; }>` grid-area: 1 / 1 / 1 / 1; @@ -194,7 +194,7 @@ const DxcSelect = ({ tabIndex = 0, value, virtualizedHeight, -}: SelectPropsType) => { +}: SelectProps) => { const id = `select-${useId()}`; const errorId = `error-${id}`; const labelId = `label-${id}`; @@ -246,7 +246,7 @@ const DxcSelect = ({ }; const handleOnChangeValue = useCallback( - (newOption?: ListOptionType | ListOptionType[]) => { + (newOption?: SelectOption | SelectOption[]) => { if (newOption) { if (multiple) { if (value == null) { @@ -448,7 +448,7 @@ const DxcSelect = ({ }; const handleOptionOnClick = useCallback( - (option: ListOptionType | ListOptionType[]) => { + (option: SelectOption | SelectOption[]) => { handleOnChangeValue(option); if (!multiple) closeListbox(); setSearchValue(""); @@ -465,7 +465,7 @@ const DxcSelect = ({ }, [handleClearOptionsActionOnClick, innerValue, multiple, onChange, options, value]); const handleSelectAllGroup = useCallback( - (group: ListOptionGroupType) => { + (group: SelectOptionGroup) => { const groupSelectionType = getGroupSelectionType(group.options, (value ?? innerValue) as string[]); handleOptionOnClick( groupSelectionType === "indeterminate" diff --git a/packages/lib/src/select/types.ts b/packages/lib/src/select/types.ts index 3157898de0..6513377211 100644 --- a/packages/lib/src/select/types.ts +++ b/packages/lib/src/select/types.ts @@ -1,12 +1,12 @@ import { CSSProperties } from "react"; -import { Margin, SVG, Space } from "../common/types"; +import { Margin, PrettifyTypes, SVG, Space } from "../common/types"; /** * Reference to the select component. */ export type RefType = React.Ref<HTMLDivElement>; -export type ListOptionType = { +export type SelectOption = { /** * Element used as the icon that will be placed before the option label. * It can be an inline SVG or Material Symbol name. If the url option @@ -26,7 +26,7 @@ export type ListOptionType = { value: string; }; -export type ListOptionGroupType = { +export type SelectOptionGroup = { /** * Label of the group to be shown in the select's listbox. */ @@ -34,7 +34,7 @@ export type ListOptionGroupType = { /** * List of the grouped options. */ - options: ListOptionType[]; + options: SelectOption[]; }; type CommonProps = { @@ -87,7 +87,7 @@ type CommonProps = { /** * An array of objects representing the selectable options. */ - options: ListOptionType[] | ListOptionGroupType[]; + options: SelectOption[] | SelectOptionGroup[]; /** * Text to be put as placeholder of the select. */ @@ -191,20 +191,20 @@ type MultipleSelect = CommonProps & { value?: string[]; }; -type Props = SingleSelect | MultipleSelect; +export type SelectProps = PrettifyTypes<SingleSelect | MultipleSelect>; /** * Single option of the select component. */ -export type OptionProps = { +export type ListboxOptionProps = { id: string; isGroupedOption?: boolean; isLastOption: boolean; isSelected: boolean; isSelectAllOption?: boolean; multiple: boolean; - option: ListOptionType; - onClick: (option: ListOptionType) => void; + option: SelectOption; + onClick: (option: SelectOption) => void; visualFocused: boolean; }; @@ -215,15 +215,15 @@ export type ListboxProps = { ariaLabelledBy: string; currentValue: string | string[]; enableSelectAll: boolean; - handleGroupOnClick: (group: ListOptionGroupType) => void; - handleOptionOnClick: (option: ListOptionType) => void; + handleGroupOnClick: (group: SelectOptionGroup) => void; + handleOptionOnClick: (option: SelectOption) => void; handleSelectAllOnClick: () => void; id: string; lastOptionIndex: number; multiple: boolean; optional: boolean; - optionalItem: ListOptionType; - options: ListOptionType[] | ListOptionGroupType[]; + optionalItem: SelectOption; + options: SelectOption[] | SelectOptionGroup[]; searchable: boolean; selectionType: "checked" | "unchecked" | "indeterminate"; styles: CSSProperties; @@ -235,7 +235,7 @@ export type FlattenedItem = | { type: "selectAll"; id?: never } | { type: "optionalItem"; id?: never } | { type: "groupLabel"; label: string; id: string } - | { type: "groupHeader"; group: ListOptionGroupType; id: string } - | { type: "option"; option: ListOptionType; id: string; isGroupedOption?: boolean }; + | { type: "groupHeader"; group: SelectOptionGroup; id: string } + | { type: "option"; option: SelectOption; id: string; isGroupedOption?: boolean }; -export default Props; +export type { SelectProps as default }; diff --git a/packages/lib/src/select/utils.ts b/packages/lib/src/select/utils.ts index 215c1b0d15..85b6f6377e 100644 --- a/packages/lib/src/select/utils.ts +++ b/packages/lib/src/select/utils.ts @@ -1,6 +1,5 @@ -import SelectPropsType, { ListOptionType, ListOptionGroupType } from "./types"; +import type { SelectOption, SelectOptionGroup, SelectProps } from "./types"; import { getMargin } from "../common/utils"; -import Props from "./types"; const sizes = { small: "240px", @@ -9,7 +8,7 @@ const sizes = { fillParent: "100%", }; -export const calculateWidth = (margin: SelectPropsType["margin"], size: SelectPropsType["size"]) => +export const calculateWidth = (margin: SelectProps["margin"], size: SelectProps["size"]) => size === "fillParent" ? `calc(${sizes[size]} - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})` : size && sizes[size]; @@ -23,20 +22,20 @@ export const notOptionalCheck = (value: string | string[], multiple: boolean, op /** * Checks if the option is a group (contains other options). */ -const isOptionGroup = (option: ListOptionType | ListOptionGroupType): option is ListOptionGroupType => +const isOptionGroup = (option: SelectOption | SelectOptionGroup): option is SelectOptionGroup => "options" in option && option.options != null; /** * Checks if the options are grouped options (groups and single options can't be mixed) */ -export const isArrayOfGroupedOptions = (options: Props["options"]): options is ListOptionGroupType[] => +export const isArrayOfGroupedOptions = (options: SelectProps["options"]): options is SelectOptionGroup[] => options[0] != null && isOptionGroup(options[0]); /** * Checks if the groups have options. If the options parameter is not an array of grouped options, * it will return true and not check nothing else. */ -export const groupsHaveOptions = (options: Props["options"]) => +export const groupsHaveOptions = (options: SelectProps["options"]) => isArrayOfGroupedOptions(options) ? options.some((groupOption) => groupOption.options.length > 0) : true; /** @@ -45,17 +44,17 @@ export const groupsHaveOptions = (options: Props["options"]) => * - The listbox has more than one single option. * - The listbox has more than one group with options contained. */ -export const canOpenListbox = (options: Props["options"], disabled: boolean) => +export const canOpenListbox = (options: SelectProps["options"], disabled: boolean) => !disabled && options.length > 0 && groupsHaveOptions(options); /** * Filters the options by the search value. */ export const filterOptionsBySearchValue = ( - options: Props["options"], + options: SelectProps["options"], searchValue: string, - searchByStartsWith: Props["searchByStartsWith"] = false -): Props["options"] => { + searchByStartsWith: SelectProps["searchByStartsWith"] = false +): SelectProps["options"] => { const matchesSearch = (label: string, search: string, searchByStartsWith: boolean) => { const upperLabel = label.toUpperCase(); const upperSearch = search.toUpperCase(); @@ -81,15 +80,15 @@ export const filterOptionsBySearchValue = ( * Returns the index of the last option, depending on several conditions. */ export const getLastOptionIndex = ( - options: Props["options"], - filteredOptions: Props["options"], + options: SelectProps["options"], + filteredOptions: SelectProps["options"], searchable: boolean, optional: boolean, multiple: boolean, enableSelectAll: boolean ) => { let last = 0; - const reducer = (acc: number, current: ListOptionGroupType) => + const reducer = (acc: number, current: SelectOptionGroup) => acc + (current.options.length ?? 0) + (enableSelectAll ? 1 : 0); if (searchable && filteredOptions.length > 0) { @@ -108,17 +107,17 @@ export const getLastOptionIndex = ( */ export const getSelectedOption = ( value: string | string[], - options: Props["options"], + options: SelectProps["options"], multiple: boolean, optional: boolean, - optionalItem: ListOptionType + optionalItem: SelectOption ) => { - let selectedOption: ListOptionType | ListOptionType[] | null = multiple ? [] : null; + let selectedOption: SelectOption | SelectOption[] | null = multiple ? [] : null; let singleSelectionIndex: number | null = null; if (multiple) { if (options.length > 0) { - options.forEach((option: ListOptionType | ListOptionGroupType) => { + options.forEach((option: SelectOption | SelectOptionGroup) => { if (isOptionGroup(option)) { option.options.forEach((singleOption) => { if (value.includes(singleOption.value) && Array.isArray(selectedOption)) { @@ -135,7 +134,7 @@ export const getSelectedOption = ( singleSelectionIndex = 0; } else if (options.length > 0) { let groupIndex = 0; - options.some((option: ListOptionType | ListOptionGroupType, index: number) => { + options.some((option: SelectOption | SelectOptionGroup, index: number) => { if (isOptionGroup(option)) { option.options.some((singleOption) => { if (singleOption.value === value) { @@ -166,10 +165,7 @@ export const getSelectedOption = ( /** * Return the label or labels of the selected option(s), separated by commas. */ -export const getSelectedOptionLabel = ( - placeholder: string, - selectedOption: ListOptionType | ListOptionType[] | null -) => +export const getSelectedOptionLabel = (placeholder: string, selectedOption: SelectOption | SelectOption[] | null) => Array.isArray(selectedOption) ? selectedOption.length === 0 ? placeholder @@ -185,7 +181,7 @@ export const getSelectedOptionLabel = ( * @param value * @returns */ -export const getSelectionType = (options: Props["options"], value: string[]) => { +export const getSelectionType = (options: SelectProps["options"], value: string[]) => { if (value.length > 0) { if ( isArrayOfGroupedOptions(options) @@ -206,7 +202,7 @@ export const getSelectionType = (options: Props["options"], value: string[]) => * @param value * @returns boolean */ -export const getGroupSelectionType = (options: ListOptionType[], value: string[]) => +export const getGroupSelectionType = (options: SelectOption[], value: string[]) => options.every((option) => value.includes(option.value)) ? "checked" : options.some((option) => value.includes(option.value)) @@ -218,7 +214,7 @@ export const getGroupSelectionType = (options: ListOptionType[], value: string[] * @param options * @returns */ -export const getSelectableOptionsValues = (options: Props["options"]) => +export const getSelectableOptionsValues = (options: SelectProps["options"]) => isArrayOfGroupedOptions(options) ? options.flatMap((group) => group.options.map((option) => option.value)) : options.map((option) => option.value); @@ -229,7 +225,7 @@ export const getSelectableOptionsValues = (options: Props["options"]) => * @param newOptions Option or array of options to toggle * @returns Updated array of values */ -export const computeNewValue = (currentValue: string[], newOptions: ListOptionType | ListOptionType[]) => { +export const computeNewValue = (currentValue: string[], newOptions: SelectOption | SelectOption[]) => { const optionsArray = Array.isArray(newOptions) ? newOptions : [newOptions]; let updatedValue = [...currentValue]; diff --git a/packages/lib/src/slider/Slider.tsx b/packages/lib/src/slider/Slider.tsx index f5e55eb6d0..eaa7a32bcc 100644 --- a/packages/lib/src/slider/Slider.tsx +++ b/packages/lib/src/slider/Slider.tsx @@ -1,7 +1,7 @@ import { ChangeEvent, MouseEvent, useId, useMemo, useState } from "react"; import styled from "@emotion/styled"; import { spaces } from "../common/variables"; -import SliderPropsType from "./types"; +import { SliderProps } from "./types"; import { calculateWidth, roundUp, stepPrecision } from "./utils"; import DxcNumberInput from "../number-input/NumberInput"; import HelperText from "../styles/forms/HelperText"; @@ -9,8 +9,8 @@ import Label from "../styles/forms/Label"; import { css } from "@emotion/react"; const SliderContainer = styled.div<{ - margin: SliderPropsType["margin"]; - size: SliderPropsType["size"]; + margin: SliderProps["margin"]; + size: SliderProps["size"]; }>` display: flex; flex-direction: column; @@ -26,7 +26,7 @@ const SliderContainer = styled.div<{ width: ${(props) => calculateWidth(props.margin, props.size)}; `; -const MainContainer = styled.div<{ showInput: SliderPropsType["showInput"] }>` +const MainContainer = styled.div<{ showInput: SliderProps["showInput"] }>` display: grid; gap: var(--spacing-gap-l); ${({ showInput }) => showInput && "grid-template-columns: 1fr 64px;"}; @@ -34,7 +34,7 @@ const MainContainer = styled.div<{ showInput: SliderPropsType["showInput"] }>` place-items: center; `; -const LimitsValueGrid = styled.div<{ showLimitsValues: SliderPropsType["showLimitsValues"] }>` +const LimitsValueGrid = styled.div<{ showLimitsValues: SliderProps["showLimitsValues"] }>` display: grid; align-items: center; gap: var(--spacing-gap-ml); @@ -43,7 +43,7 @@ const LimitsValueGrid = styled.div<{ showLimitsValues: SliderPropsType["showLimi `; const LimitLabel = styled.span<{ - disabled: SliderPropsType["disabled"]; + disabled: SliderProps["disabled"]; }>` color: ${({ disabled }) => (disabled ? "var(--color-fg-neutral-medium)" : "var(--color-fg-neutral-dark)")}; font-family: var(--typography-font-family); @@ -59,7 +59,7 @@ const SliderInputContainer = styled.div` min-width: 184px; `; -const thumbStyles = (disabled: SliderPropsType["disabled"]) => css` +const thumbStyles = (disabled: SliderProps["disabled"]) => css` -webkit-appearance: none; width: 12px; height: var(--height-xxxs); @@ -86,10 +86,10 @@ const thumbFocusStyles = css` outline-offset: 2px; `; const SliderInput = styled.input<{ - disabled: SliderPropsType["disabled"]; - max: Required<SliderPropsType>["maxValue"]; - min: Required<SliderPropsType>["minValue"]; - value: Required<SliderPropsType>["value"]; + disabled: SliderProps["disabled"]; + max: Required<SliderProps>["maxValue"]; + min: Required<SliderProps>["minValue"]; + value: Required<SliderProps>["value"]; }>` -webkit-appearance: none; margin: 0; @@ -136,7 +136,7 @@ const TicksContainer = styled.datalist` `; const Tick = styled.option<{ - disabled: SliderPropsType["disabled"]; + disabled: SliderProps["disabled"]; currentTick: boolean; }>` all: unset; @@ -168,7 +168,7 @@ const DxcSlider = ({ size = "fillParent", step = 1, value, -}: SliderPropsType) => { +}: SliderProps) => { const labelId = `label-${useId()}`; const [innerValue, setInnerValue] = useState(defaultValue); const [inputValue, setInputValue] = useState((value ?? defaultValue).toString()); diff --git a/packages/lib/src/slider/types.ts b/packages/lib/src/slider/types.ts index 5cd03af39d..57b8184440 100644 --- a/packages/lib/src/slider/types.ts +++ b/packages/lib/src/slider/types.ts @@ -5,7 +5,7 @@ import { Margin, Space } from "../common/types"; */ export type RefType = React.Ref<HTMLDivElement>; -type Props = { +export type SliderProps = { /** * Specifies a string to be used as the name for the slider element when no `label` is provided. */ @@ -88,4 +88,4 @@ type Props = { value?: number; }; -export default Props; +export type { SliderProps as default }; diff --git a/packages/lib/src/slider/utils.ts b/packages/lib/src/slider/utils.ts index a1345438a6..981f5090ee 100644 --- a/packages/lib/src/slider/utils.ts +++ b/packages/lib/src/slider/utils.ts @@ -1,4 +1,4 @@ -import SliderPropsType from "./types"; +import { SliderProps } from "./types"; import { getMargin } from "../common/utils"; const sizes = { @@ -7,7 +7,7 @@ const sizes = { fillParent: "100%", }; -export const calculateWidth = (margin: SliderPropsType["margin"], size: SliderPropsType["size"]) => +export const calculateWidth = (margin: SliderProps["margin"], size: SliderProps["size"]) => size === "fillParent" ? `calc(${sizes[size]} - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})` : size && sizes[size]; diff --git a/packages/lib/src/spinner/Spinner.tsx b/packages/lib/src/spinner/Spinner.tsx index 792c40adb5..c8818b75d0 100644 --- a/packages/lib/src/spinner/Spinner.tsx +++ b/packages/lib/src/spinner/Spinner.tsx @@ -1,12 +1,12 @@ import { MouseEvent, useId, useMemo, useState } from "react"; import styled from "@emotion/styled"; import { spaces } from "../common/variables"; -import SpinnerPropsType from "./types"; +import { SpinnerProps } from "./types"; import { TooltipWrapper } from "../tooltip/Tooltip"; const SpinnerContainer = styled.div<{ - margin: SpinnerPropsType["margin"]; - mode: SpinnerPropsType["mode"]; + margin: SpinnerProps["margin"]; + mode: SpinnerProps["mode"]; }>` ${({ mode }) => mode === "overlay" && @@ -48,7 +48,7 @@ const SpinnerContainer = styled.div<{ : ""}; `; -const MainContainer = styled.div<{ mode: SpinnerPropsType["mode"] }>` +const MainContainer = styled.div<{ mode: SpinnerProps["mode"] }>` position: relative; display: grid; place-items: center; @@ -106,7 +106,7 @@ const SVGTotalTrack = styled.svg` width: inherit; `; -const TotalTrack = styled.circle<{ mode: SpinnerPropsType["mode"] }>` +const TotalTrack = styled.circle<{ mode: SpinnerProps["mode"] }>` animation: none; fill: transparent; stroke: var(--color-bg-neutral-lightest); @@ -134,13 +134,13 @@ const SVGSpinner = styled.svg<{ determined: boolean }>` animation: ${({ determined }) => !determined && "1.4s linear infinite both spinner-svg"}; `; -const determinateValue = (value: SpinnerPropsType["value"], strokeDashArray: number) => +const determinateValue = (value: SpinnerProps["value"], strokeDashArray: number) => value != null && value >= 0 && value <= 100 ? strokeDashArray * (1 - value / 100) : 0; const CircleSpinner = styled.circle<{ determined: boolean; - inheritColor: SpinnerPropsType["inheritColor"]; - value: SpinnerPropsType["value"]; + inheritColor: SpinnerProps["inheritColor"]; + value: SpinnerProps["value"]; }>` fill: transparent; stroke-linecap: initial; @@ -164,7 +164,7 @@ const CircleSpinner = styled.circle<{ determined ? (mode !== "small" ? determinateValue(value, 409) : determinateValue(value, 38)) : ""}; `; -const Labels = styled.div<{ mode: SpinnerPropsType["mode"] }>` +const Labels = styled.div<{ mode: SpinnerProps["mode"] }>` position: absolute; display: grid; gap: var(--spacing-gap-none); @@ -194,7 +194,7 @@ const DxcSpinner = ({ mode = "large", showValue, value, -}: SpinnerPropsType) => { +}: SpinnerProps) => { const labelId = useId(); const determined = useMemo(() => value != null && value >= 0 && value <= 100, [value]); const [hasTooltip, setHasTooltip] = useState(false); diff --git a/packages/lib/src/spinner/types.ts b/packages/lib/src/spinner/types.ts index 37f66f8aa8..7e8818fc89 100644 --- a/packages/lib/src/spinner/types.ts +++ b/packages/lib/src/spinner/types.ts @@ -1,6 +1,6 @@ import { Margin, Space } from "../common/types"; -type Props = { +export type SpinnerProps = { /** * Specifies a string to be used as the name for the spinner element when no `label` is provided or the `mode` is set to small. */ @@ -34,4 +34,4 @@ type Props = { value?: number; }; -export default Props; +export type { SpinnerProps as default }; diff --git a/packages/lib/src/status-light/StatusLight.tsx b/packages/lib/src/status-light/StatusLight.tsx index 009652d642..1e4f7b6c86 100644 --- a/packages/lib/src/status-light/StatusLight.tsx +++ b/packages/lib/src/status-light/StatusLight.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; -import StatusLightPropsType from "./types"; +import iStatusLightProps from "./types"; -const getModeColor = (mode: Required<StatusLightPropsType>["mode"]) => { +const getModeColor = (mode: Required<iStatusLightProps>["mode"]) => { switch (mode) { case "default": return "var(--color-fg-neutral-strong);"; @@ -16,7 +16,7 @@ const getModeColor = (mode: Required<StatusLightPropsType>["mode"]) => { } }; -const getSizeValues = (size: Required<StatusLightPropsType>["size"]) => { +const getSizeValues = (size: Required<iStatusLightProps>["size"]) => { switch (size) { case "small": return { @@ -36,7 +36,7 @@ const getSizeValues = (size: Required<StatusLightPropsType>["size"]) => { } }; -const StatusLightContainer = styled.div<{ size: Required<StatusLightPropsType>["size"] }>` +const StatusLightContainer = styled.div<{ size: Required<iStatusLightProps>["size"] }>` display: inline-flex; align-items: center; gap: ${({ size }) => (size === "small" ? "var(--spacing-gap-xs)" : "var(--spacing-gap-s)")}; @@ -44,8 +44,8 @@ const StatusLightContainer = styled.div<{ size: Required<StatusLightPropsType>[" `; const Dot = styled.div<{ - mode: Required<StatusLightPropsType>["mode"]; - size: Required<StatusLightPropsType>["size"]; + mode: Required<iStatusLightProps>["mode"]; + size: Required<iStatusLightProps>["size"]; }>` background-color: ${({ mode }) => getModeColor(mode)}; border-radius: 50%; @@ -55,8 +55,8 @@ const Dot = styled.div<{ `; const Label = styled.span<{ - mode: Required<StatusLightPropsType>["mode"]; - size: Required<StatusLightPropsType>["size"]; + mode: Required<iStatusLightProps>["mode"]; + size: Required<iStatusLightProps>["size"]; }>` color: ${({ mode }) => getModeColor(mode)}; font-family: var(--typography-font-family); @@ -67,7 +67,7 @@ const Label = styled.span<{ white-space: nowrap; `; -export default function DxcStatusLight({ label, mode = "default", size = "medium" }: StatusLightPropsType) { +export default function DxcStatusLight({ label, mode = "default", size = "medium" }: iStatusLightProps) { return ( <StatusLightContainer role="status" size={size}> <Dot mode={mode} size={size} aria-hidden="true" /> diff --git a/packages/lib/src/status-light/types.ts b/packages/lib/src/status-light/types.ts index be41ce9b35..e65c14650f 100644 --- a/packages/lib/src/status-light/types.ts +++ b/packages/lib/src/status-light/types.ts @@ -1,7 +1,6 @@ -type Mode = "default" | "info" | "success" | "warning" | "error"; -type Size = "small" | "medium" | "large"; +import { Mode } from "../common/types"; -type Props = { +export type StatusLightProps = { /** * It will define the color of the light based on its semantic meaning. */ @@ -13,7 +12,7 @@ type Props = { /** * Size of the component. Should be defined based on its importance and/or available space. */ - size?: Size; + size?: "small" | "medium" | "large"; }; -export default Props; +export type { StatusLightProps as default }; diff --git a/packages/lib/src/switch/Switch.tsx b/packages/lib/src/switch/Switch.tsx index 08cd1d0afe..785098895b 100644 --- a/packages/lib/src/switch/Switch.tsx +++ b/packages/lib/src/switch/Switch.tsx @@ -3,7 +3,7 @@ import styled from "@emotion/styled"; import { spaces } from "../common/variables"; import { getMargin } from "../common/utils"; import { HalstackLanguageContext } from "../HalstackContext"; -import SwitchPropsType from "./types"; +import { SwitchProps } from "./types"; const sizes = { small: "60px", @@ -13,12 +13,12 @@ const sizes = { fitContent: "fit-content", }; -const calculateWidth = (margin: SwitchPropsType["margin"], size: SwitchPropsType["size"]) => +const calculateWidth = (margin: SwitchProps["margin"], size: SwitchProps["size"]) => size === "fillParent" ? `calc(${sizes[size]} - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})` : size && sizes[size]; -const getTrackColor = (checked: SwitchPropsType["checked"], disabled: SwitchPropsType["disabled"]) => +const getTrackColor = (checked: SwitchProps["checked"], disabled: SwitchProps["disabled"]) => disabled ? checked ? "var(--color-bg-primary-lighter)" @@ -28,10 +28,10 @@ const getTrackColor = (checked: SwitchPropsType["checked"], disabled: SwitchProp : "var(--color-bg-neutral-strong)"; const SwitchContainer = styled.div<{ - disabled: SwitchPropsType["disabled"]; - labelPosition: SwitchPropsType["labelPosition"]; - margin: SwitchPropsType["margin"]; - size: SwitchPropsType["size"]; + disabled: SwitchProps["disabled"]; + labelPosition: SwitchProps["labelPosition"]; + margin: SwitchProps["margin"]; + size: SwitchProps["size"]; }>` display: inline-grid; grid-template-columns: ${({ labelPosition }) => @@ -61,8 +61,8 @@ const SwitchContainer = styled.div<{ `; const LabelContainer = styled.span<{ - disabled: SwitchPropsType["disabled"]; - labelPosition: SwitchPropsType["labelPosition"]; + disabled: SwitchProps["disabled"]; + labelPosition: SwitchProps["labelPosition"]; }>` display: flex; gap: var(--spacing-gap-xs); @@ -81,12 +81,12 @@ const Label = styled.span` `; const OptionalLabel = styled.span<{ - disabled: SwitchPropsType["disabled"]; + disabled: SwitchProps["disabled"]; }>` ${({ disabled }) => !disabled && "color: var(--color-fg-neutral-stronger);"} `; -const Switch = styled.span<{ checked: SwitchPropsType["checked"]; disabled: SwitchPropsType["disabled"] }>` +const Switch = styled.span<{ checked: SwitchProps["checked"]; disabled: SwitchProps["disabled"] }>` position: relative; width: 36px; height: var(--height-xxxs); @@ -125,7 +125,7 @@ const DxcSwitch = ({ size = "fitContent", tabIndex = 0, value, -}: SwitchPropsType) => { +}: SwitchProps) => { const [innerChecked, setInnerChecked] = useState(defaultChecked); const translatedLabels = use(HalstackLanguageContext).labels; diff --git a/packages/lib/src/switch/types.ts b/packages/lib/src/switch/types.ts index babff51519..9919d700ea 100644 --- a/packages/lib/src/switch/types.ts +++ b/packages/lib/src/switch/types.ts @@ -5,7 +5,7 @@ import { Margin, Space } from "../common/types"; */ export type RefType = React.Ref<HTMLDivElement>; -type Props = { +export type SwitchProps = { /** * Specifies a string to be used as the name for the switch element when no `label` is provided. */ @@ -68,4 +68,4 @@ type Props = { value?: string; }; -export default Props; +export type { SwitchProps as default }; diff --git a/packages/lib/src/table/Table.tsx b/packages/lib/src/table/Table.tsx index 9f5d8a392c..36f1a6b3e1 100644 --- a/packages/lib/src/table/Table.tsx +++ b/packages/lib/src/table/Table.tsx @@ -3,14 +3,14 @@ import { spaces } from "../common/variables"; import { getMargin } from "../common/utils"; import DxcDropdown from "../dropdown/Dropdown"; import DxcActionIcon from "../action-icon/ActionIcon"; -import TablePropsType, { ActionsCellPropsType } from "./types"; +import { TableProps, ActionsCellProps } from "./types"; import scrollbarStyles from "../styles/scroll"; import { useMemo } from "react"; -const calculateWidth = (margin: TablePropsType["margin"]) => +const calculateWidth = (margin: TableProps["margin"]) => `calc(100% - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})`; -const TableContainer = styled.div<{ margin: TablePropsType["margin"] }>` +const TableContainer = styled.div<{ margin: TableProps["margin"] }>` width: ${({ margin }) => calculateWidth(margin)}; margin: ${({ margin }) => (margin && typeof margin !== "object" ? spaces[margin] : "0px")}; margin-top: ${({ margin }) => (margin && typeof margin === "object" && margin.top ? spaces[margin.top] : "")}; @@ -22,7 +22,7 @@ const TableContainer = styled.div<{ margin: TablePropsType["margin"] }>` ${scrollbarStyles} `; -const Table = styled.table<{ mode: TablePropsType["mode"] }>` +const Table = styled.table<{ mode: TableProps["mode"] }>` border-collapse: collapse; width: 100%; @@ -81,7 +81,7 @@ const ActionsContainer = styled.div` } `; -const DxcActionsCell = ({ actions }: ActionsCellPropsType) => { +const DxcActionsCell = ({ actions }: ActionsCellProps) => { const actionIcons = useMemo(() => actions.filter((action) => !action.options), [actions]); const dropdownAction = useMemo(() => actions.find((action) => action.options), [actions]); @@ -116,7 +116,7 @@ const DxcActionsCell = ({ actions }: ActionsCellPropsType) => { ); }; -const DxcTable = ({ children, margin, mode = "default" }: TablePropsType) => ( +const DxcTable = ({ children, margin, mode = "default" }: TableProps) => ( <TableContainer margin={margin}> <Table mode={mode}>{children}</Table> </TableContainer> diff --git a/packages/lib/src/table/types.ts b/packages/lib/src/table/types.ts index af2a478784..9afcb70a61 100644 --- a/packages/lib/src/table/types.ts +++ b/packages/lib/src/table/types.ts @@ -1,6 +1,6 @@ import { ReactNode } from "react"; -import { Margin, SVG, Space } from "../common/types"; -import { Option } from "../dropdown/types"; +import { Margin, PrettifyTypes, SVG, Space } from "../common/types"; +import { DropdownOption } from "../dropdown/types"; type BaseActionCell = { disabled?: boolean; @@ -8,31 +8,33 @@ type BaseActionCell = { title: string; }; -type ActionCell = BaseActionCell & - ( - | { - icon: string | SVG; - onClick: () => void; - options?: never; - } - | { - icon?: never; - onClick: (value?: string) => void; - options: Option[]; - } - ); +export type TableActionCell = PrettifyTypes< + BaseActionCell & + ( + | { + icon: string | SVG; + onClick: () => void; + options?: never; + } + | { + icon?: never; + onClick: (value?: string) => void; + options: DropdownOption[]; + } + ) +>; -export type ActionsCellPropsType = { +export type ActionsCellProps = { /** * It represents a list of interactive elements that will work as buttons or as a dropdown. Those with an icon from Material Symbols * or a SVG are treated as buttons. If any element lacks an icon and includes options, it is interpreted as a dropdown. * Only the first action with options will be displayed and only up to 3 actions. * In the case of the dropdown the click function will pass the value assigned to the option. */ - actions: ActionCell[]; + actions: TableActionCell[]; }; -type Props = { +export type TableProps = { /** * The center section of the table. Can be used to render custom * content in this area. @@ -51,4 +53,4 @@ type Props = { mode?: "default" | "reduced"; }; -export default Props; +export type { TableProps as default }; diff --git a/packages/lib/src/table/utils.ts b/packages/lib/src/table/utils.ts index 2b7f635d1e..1b8914b6c3 100644 --- a/packages/lib/src/table/utils.ts +++ b/packages/lib/src/table/utils.ts @@ -1,5 +1,5 @@ import { getMargin } from "../common/utils"; -import TablePropsType from "./types"; +import { TableProps } from "./types"; -export const calculateWidth = (margin: TablePropsType["margin"]) => +export const calculateWidth = (margin: TableProps["margin"]) => `calc(100% - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})`; diff --git a/packages/lib/src/tabs/Tab.tsx b/packages/lib/src/tabs/Tab.tsx index 84283f2725..91dc0aeb47 100644 --- a/packages/lib/src/tabs/Tab.tsx +++ b/packages/lib/src/tabs/Tab.tsx @@ -4,7 +4,7 @@ import DxcBadge from "../badge/Badge"; import DxcIcon from "../icon/Icon"; import { Tooltip } from "../tooltip/Tooltip"; import TabsContext from "./TabsContext"; -import { TabProps, TabsContextProps } from "./types"; +import { TabsTabProps, TabsContextProps } from "./types"; export const sharedTabStyles = ` background-color: var(--color-bg-neutral-lightest); @@ -103,7 +103,7 @@ const DxcTab = ({ ref, title, tabId = label, -}: TabProps) => { +}: TabsTabProps) => { const { activeTabId, focusedTabId, diff --git a/packages/lib/src/tabs/Tabs.stories.tsx b/packages/lib/src/tabs/Tabs.stories.tsx index 29b071df9a..3eac76565c 100644 --- a/packages/lib/src/tabs/Tabs.stories.tsx +++ b/packages/lib/src/tabs/Tabs.stories.tsx @@ -1,7 +1,7 @@ import ExampleContainer from "../../.storybook/components/ExampleContainer"; import Title from "../../.storybook/components/Title"; import DxcTabs from "./Tabs"; -import type { Margin, Space } from "../common/utils"; +import type { Margin, Space } from "../common/types"; import { Meta, StoryObj } from "@storybook/react-vite"; import { userEvent, within } from "storybook/test"; diff --git a/packages/lib/src/tabs/Tabs.tsx b/packages/lib/src/tabs/Tabs.tsx index 98ddfed390..60634c4d9a 100644 --- a/packages/lib/src/tabs/Tabs.tsx +++ b/packages/lib/src/tabs/Tabs.tsx @@ -13,14 +13,14 @@ import { import styled from "@emotion/styled"; import TabsContext from "./TabsContext"; import DxcTab, { sharedTabStyles } from "./Tab"; -import TabsPropsType, { TabProps } from "./types"; +import { TabsProps, TabsTabProps } from "./types"; import { spaces } from "../common/variables"; import { HalstackLanguageContext } from "../HalstackContext"; import DxcIcon from "../icon/Icon"; import { getPreviousTabIndex, getNextTabIndex } from "./utils"; import useWidth from "../utils/useWidth"; -const TabsContainer = styled.div<{ margin: TabsPropsType["margin"] }>` +const TabsContainer = styled.div<{ margin: TabsProps["margin"] }>` position: relative; margin: ${(props) => (props.margin && typeof props.margin !== "object" ? spaces[props.margin] : "0px")}; margin-top: ${(props) => @@ -81,15 +81,15 @@ const TabsContent = styled.div` const ScrollableTabsList = styled.div<{ enabled: boolean; - iconPosition: TabsPropsType["iconPosition"]; + iconPosition: TabsProps["iconPosition"]; }>` display: flex; transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; height: ${({ iconPosition }) => (iconPosition === "top" ? "72px" : "var(--height-xxl)")}; `; -const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: TabsPropsType) => { - const isTabElement = (child: ReactNode): child is ReactElement<TabProps> => isValidElement<TabProps>(child); +const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: TabsProps) => { + const isTabElement = (child: ReactNode): child is ReactElement<TabsTabProps> => isValidElement<TabsTabProps>(child); const childrenArray = useMemo(() => Children.toArray(children).filter(isTabElement), [children]); const [activeTabId, setActiveTabId] = useState<string>(() => { const activeChild = childrenArray.find( diff --git a/packages/lib/src/tabs/types.ts b/packages/lib/src/tabs/types.ts index ba6fd7decc..c9bf36744c 100644 --- a/packages/lib/src/tabs/types.ts +++ b/packages/lib/src/tabs/types.ts @@ -1,6 +1,6 @@ import { ReactNode } from "react"; -import type { Space, Margin, SVG } from "../common/types"; +import type { Space, Margin, SVG, PrettifyTypes } from "../common/types"; export type TabsContextProps = { activeTabId?: string; @@ -23,11 +23,15 @@ type CommonTabProps = { ref?: React.Ref<HTMLButtonElement>; }; -export type TabProps = - | (CommonTabProps & { tabId: string; label?: string; icon?: string | SVG }) - | (CommonTabProps & { tabId?: string; label: string; icon?: string | SVG }); +export type TabsTabProps = PrettifyTypes< + CommonTabProps & + ( + | { tabId: string; label?: string; icon?: string | SVG } + | (CommonTabProps & { tabId?: string; label: string; icon?: string | SVG }) + ) +>; -type TabsProps = { +export type TabsProps = { /** * Whether the icon should appear above or to the left of the label. */ @@ -47,6 +51,4 @@ type TabsProps = { children?: ReactNode; }; -type Props = TabsProps; - -export default Props; +export type { TabsProps as default }; diff --git a/packages/lib/src/text-input/TextInput.tsx b/packages/lib/src/text-input/TextInput.tsx index a77ca3c266..ad124a202c 100644 --- a/packages/lib/src/text-input/TextInput.tsx +++ b/packages/lib/src/text-input/TextInput.tsx @@ -20,7 +20,7 @@ import NumberInputContext from "../number-input/NumberInputContext"; import { HalstackLanguageContext } from "../HalstackContext"; import useWidth from "../utils/useWidth"; import Suggestions from "./Suggestions"; -import TextInputPropsType, { AutosuggestWrapperProps } from "./types"; +import { TextInputProps, AutosuggestWrapperProps } from "./types"; import { calculateWidth, decrementNumber, @@ -41,8 +41,8 @@ import { getLengthErrorMessage } from "../common/utils"; import DxcPopover from "../popover/Popover"; const TextInputContainer = styled.div<{ - margin: TextInputPropsType["margin"]; - size: TextInputPropsType["size"]; + margin: TextInputProps["margin"]; + size: TextInputProps["size"]; }>` box-sizing: border-box; display: flex; @@ -58,9 +58,9 @@ const TextInputContainer = styled.div<{ `; const TextInput = styled.div<{ - disabled: Required<TextInputPropsType>["disabled"]; + disabled: Required<TextInputProps>["disabled"]; error: boolean; - readOnly: Required<TextInputPropsType>["readOnly"]; + readOnly: Required<TextInputProps>["readOnly"]; }>` position: relative; display: flex; @@ -72,7 +72,7 @@ const TextInput = styled.div<{ `; const Input = styled.input<{ - alignment: TextInputPropsType["alignment"]; + alignment: TextInputProps["alignment"]; }>` max-width: 100%; background: none; @@ -96,7 +96,7 @@ const Input = styled.input<{ ${({ disabled }) => disabled && "cursor: not-allowed;"} `; -const Addon = styled.span<{ disabled: TextInputPropsType["disabled"]; type: "prefix" | "suffix" }>` +const Addon = styled.span<{ disabled: TextInputProps["disabled"]; type: "prefix" | "suffix" }>` ${({ disabled, type }) => { const color = disabled ? "var(--color-fg-neutral-medium)" : "var(--color-fg-neutral-stronger)"; return `color: ${color}; border-${type === "prefix" ? "right" : "left"}: var(--border-width-s) var(--border-style-default) ${color};`; @@ -140,7 +140,7 @@ const DxcTextInput = ({ suggestions, tabIndex = 0, value, -}: TextInputPropsType) => { +}: TextInputProps) => { const inputId = `input-${useId()}`; const autosuggestId = `suggestions-${inputId}`; const errorId = `error-${inputId}`; diff --git a/packages/lib/src/text-input/types.ts b/packages/lib/src/text-input/types.ts index e83a29a0c7..df06968593 100644 --- a/packages/lib/src/text-input/types.ts +++ b/packages/lib/src/text-input/types.ts @@ -1,24 +1,7 @@ import { JSX, CSSProperties, ReactNode } from "react"; -import { Margin, SVG, Space } from "../common/types"; +import { Margin, Action, Space } from "../common/types"; -type Action = { - /** - * This function will be called when the user clicks the action. - */ - onClick: () => void; - /** - * Icon to be placed in the action.. - */ - icon: string | SVG; - /** - * Text representing advisory information related - * to the button's action. Under the hood, this prop also serves - * as an accessible label for the component. - */ - title?: string; -}; - -type Props = { +export type TextInputProps = { /** * Sets the alignment inside the input. */ @@ -208,4 +191,4 @@ export type AutosuggestWrapperProps = { children: ReactNode; }; -export default Props; +export type { TextInputProps as default }; diff --git a/packages/lib/src/text-input/utils.ts b/packages/lib/src/text-input/utils.ts index c8e99966ca..0d6faffe58 100644 --- a/packages/lib/src/text-input/utils.ts +++ b/packages/lib/src/text-input/utils.ts @@ -1,4 +1,4 @@ -import TextInputPropsType from "./types"; +import { TextInputProps } from "./types"; import { getMargin } from "../common/utils"; const sizes = { @@ -8,7 +8,7 @@ const sizes = { fillParent: "100%", }; -export const calculateWidth = (margin: TextInputPropsType["margin"], size: TextInputPropsType["size"]) => +export const calculateWidth = (margin: TextInputProps["margin"], size: TextInputProps["size"]) => size === "fillParent" ? `calc(${sizes[size]} - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})` : size && sizes[size]; @@ -43,18 +43,18 @@ export const makeCancelable = (promise: Promise<string[]>) => { }; }; -export const hasSuggestions = (suggestions: TextInputPropsType["suggestions"]) => +export const hasSuggestions = (suggestions: TextInputProps["suggestions"]) => typeof suggestions === "function" || (suggestions ? suggestions.length > 0 : false); export const isRequired = (value: string, optional: boolean) => value === "" && !optional; export const isNumberIncorrect = ( value: number, - minNumber: TextInputPropsType["minLength"], - maxNumber: TextInputPropsType["maxLength"] + minNumber: TextInputProps["minLength"], + maxNumber: TextInputProps["maxLength"] ) => (minNumber != null && value < minNumber) || (maxNumber != null && value > maxNumber); -export const patternMismatch = (pattern: TextInputPropsType["pattern"], value: string) => +export const patternMismatch = (pattern: TextInputProps["pattern"], value: string) => pattern != null && !new RegExp(pattern).test(value); export const transformSpecialChars = (str: string) => { diff --git a/packages/lib/src/textarea/types.ts b/packages/lib/src/textarea/types.ts index 102fe716d5..4f859a50a4 100644 --- a/packages/lib/src/textarea/types.ts +++ b/packages/lib/src/textarea/types.ts @@ -5,7 +5,7 @@ import { Margin, Space } from "../common/types"; */ export type RefType = React.Ref<HTMLDivElement>; -type Props = { +export type TextAreaProps = { /** * Specifies a string to be used as the name for the textarea element when no `label` is provided. */ @@ -137,4 +137,4 @@ type Props = { verticalGrow?: "auto" | "manual" | "none"; }; -export default Props; +export type { TextAreaProps as default }; diff --git a/packages/lib/src/time-input/TimeInput.tsx b/packages/lib/src/time-input/TimeInput.tsx index 4da62b14a1..354a877b9a 100644 --- a/packages/lib/src/time-input/TimeInput.tsx +++ b/packages/lib/src/time-input/TimeInput.tsx @@ -1,6 +1,6 @@ import styled from "@emotion/styled"; import inputStylesByState from "../styles/forms/inputStylesByState"; -import TimeInputPropsType from "./types"; +import { TimeInputProps } from "./types"; import { use, useEffect, useId, useMemo, useRef, useState } from "react"; import { HalstackLanguageContext } from "../HalstackContext"; import Label from "../styles/forms/Label"; @@ -21,7 +21,7 @@ const sizes = { }; const TimeInputContainer = styled.div<{ - size: TimeInputPropsType["size"]; + size: TimeInputProps["size"]; }>` box-sizing: border-box; display: flex; @@ -34,9 +34,9 @@ const TimeInputContainer = styled.div<{ `; const TimeInputField = styled.div<{ - disabled: Required<TimeInputPropsType>["disabled"]; + disabled: Required<TimeInputProps>["disabled"]; error: boolean; - readOnly: Required<TimeInputPropsType>["readOnly"]; + readOnly: Required<TimeInputProps>["readOnly"]; }>` position: relative; display: flex; @@ -74,7 +74,7 @@ const DxcTimeInput = ({ tabIndex = 0, timeFormat, value, -}: TimeInputPropsType) => { +}: TimeInputProps) => { const inputId = `input-${useId()}`; const errorId = `error-${useId()}`; const [hourValue, setHourValue] = useState<number | undefined>(undefined); diff --git a/packages/lib/src/time-input/TimePicker.tsx b/packages/lib/src/time-input/TimePicker.tsx index 28d7bab465..d77defa8cf 100644 --- a/packages/lib/src/time-input/TimePicker.tsx +++ b/packages/lib/src/time-input/TimePicker.tsx @@ -1,5 +1,5 @@ import styled from "@emotion/styled"; -import { TimePickerPropsType } from "./types"; +import { TimePickerProps } from "./types"; import { use, useEffect, useState } from "react"; import TimePickerColumn from "./TimePickerColumn"; import { handleColumnKeyDown } from "./utils"; @@ -25,7 +25,7 @@ const TimePicker = ({ dayPeriod, id, tabIndex = 0, -}: TimePickerPropsType) => { +}: TimePickerProps) => { const [hourToFocus, setHourToFocus] = useState(hourValue ?? (timeFormat === "12" ? 1 : 0)); const [minuteToFocus, setMinuteToFocus] = useState(minuteValue ?? 0); const [secondToFocus, setSecondToFocus] = useState(secondValue ?? 0); diff --git a/packages/lib/src/time-input/TimeSpinButton.tsx b/packages/lib/src/time-input/TimeSpinButton.tsx index 24e0991f5b..ac391863da 100644 --- a/packages/lib/src/time-input/TimeSpinButton.tsx +++ b/packages/lib/src/time-input/TimeSpinButton.tsx @@ -1,5 +1,5 @@ import styled from "@emotion/styled"; -import { TimeSpinButtonPropsType } from "./types"; +import { TimeSpinButtonProps } from "./types"; import { use, useEffect, useMemo, useRef, useState } from "react"; import { handleKeyDown, pad, returnDayPeriod, generateDisplayValue } from "./utils"; import { HalstackLanguageContext } from "../HalstackContext"; @@ -43,7 +43,7 @@ const TimeSpinButton = ({ onComplete, onNext, onPrevious, -}: TimeSpinButtonPropsType) => { +}: TimeSpinButtonProps) => { const [innerValue, setInnerValue] = useState<number | undefined>(value); const spanRef = useRef<HTMLSpanElement | null>(null); const translatedLabels = use(HalstackLanguageContext).labels; diff --git a/packages/lib/src/time-input/types.ts b/packages/lib/src/time-input/types.ts index d801c07667..d2ba6aa7f1 100644 --- a/packages/lib/src/time-input/types.ts +++ b/packages/lib/src/time-input/types.ts @@ -3,7 +3,7 @@ */ export type RefType = React.Ref<HTMLDivElement>; -type Props = { +export type TimeInputProps = { /** * Specifies a string to be used as the name for the timeInput element when no `label` is provided. */ @@ -91,7 +91,7 @@ type Props = { value?: string; }; -export type TimeSpinButtonPropsType = { +export type TimeSpinButtonProps = { ariaLabel?: string; value: number | undefined; minValue: number; @@ -108,7 +108,7 @@ export type TimeSpinButtonPropsType = { onPrevious?: () => void; }; -export type TimePickerPropsType = { +export type TimePickerProps = { onPickTime: (hours: number, minutes: number, seconds?: number, dayPeriod?: number) => void; timeFormat: "12" | "24"; dayPeriodPosition?: "before" | "after"; @@ -121,4 +121,4 @@ export type TimePickerPropsType = { tabIndex?: number; }; -export default Props; +export type { TimeInputProps as default }; diff --git a/packages/lib/src/toast/Toast.tsx b/packages/lib/src/toast/Toast.tsx index 93121f0aee..5a4c6ef9f2 100644 --- a/packages/lib/src/toast/Toast.tsx +++ b/packages/lib/src/toast/Toast.tsx @@ -4,7 +4,7 @@ import styled from "@emotion/styled"; import DxcButton from "../button/Button"; import DxcFlex from "../flex/Flex"; import { HalstackLanguageContext } from "../HalstackContext"; -import ToastPropsType from "./types"; +import { ToastProps } from "./types"; import useTimeout from "../utils/useTimeout"; import { responsiveSizes } from "../common/variables"; import getSemantic from "./utils"; @@ -33,7 +33,7 @@ const fadeOutDown = keyframes` } `; -const Toast = styled.output<{ semantic: ToastPropsType["semantic"]; isClosing: boolean }>` +const Toast = styled.output<{ semantic: ToastProps["semantic"]; isClosing: boolean }>` box-sizing: border-box; min-width: 200px; max-width: 600px; @@ -57,7 +57,7 @@ const Toast = styled.output<{ semantic: ToastPropsType["semantic"]; isClosing: b } `; -const ContentContainer = styled.div<{ loading: ToastPropsType["loading"]; semantic: ToastPropsType["semantic"] }>` +const ContentContainer = styled.div<{ loading: ToastProps["loading"]; semantic: ToastProps["semantic"] }>` display: flex; align-items: center; gap: var(--spacing-gap-s); @@ -80,16 +80,7 @@ const Message = styled.span` white-space: nowrap; `; -const DxcToast = ({ - action, - duration, - hideSemanticIcon, - icon, - loading, - message, - onClear, - semantic, -}: ToastPropsType) => { +const DxcToast = ({ action, duration, hideSemanticIcon, icon, loading, message, onClear, semantic }: ToastProps) => { const [isClosing, setIsClosing] = useState(false); const toastRef = useRef<HTMLOutputElement>(null); const previouslyFocusedElement = useRef<HTMLElement | null>(null); diff --git a/packages/lib/src/toast/ToastContext.tsx b/packages/lib/src/toast/ToastContext.tsx index e4f07e111a..1c239254a6 100644 --- a/packages/lib/src/toast/ToastContext.tsx +++ b/packages/lib/src/toast/ToastContext.tsx @@ -1,4 +1,4 @@ import { createContext } from "react"; -import { ToastContextType } from "./types"; +import { ToastContext } from "./types"; -export default createContext<ToastContextType | null>(null); +export default createContext<ToastContext | null>(null); diff --git a/packages/lib/src/toast/ToastIcon.tsx b/packages/lib/src/toast/ToastIcon.tsx index 4e1652d51b..a843b3368e 100644 --- a/packages/lib/src/toast/ToastIcon.tsx +++ b/packages/lib/src/toast/ToastIcon.tsx @@ -1,7 +1,7 @@ import { memo } from "react"; import { DxcSpinner } from ".."; import DxcIcon from "../icon/Icon"; -import ToastPropsType from "./types"; +import { ToastProps } from "./types"; import getSemantic from "./utils"; const ToastIcon = memo( @@ -10,7 +10,7 @@ const ToastIcon = memo( hideSemanticIcon, loading, semantic, - }: Pick<ToastPropsType, "icon" | "hideSemanticIcon" | "loading" | "semantic">) => { + }: Pick<ToastProps, "icon" | "hideSemanticIcon" | "loading" | "semantic">) => { if (semantic === "default") return typeof icon === "string" ? <DxcIcon icon={icon} /> : icon; else if (semantic === "info" && loading) return <DxcSpinner inheritColor mode="small" />; else return !hideSemanticIcon && <DxcIcon icon={getSemantic(semantic).icon} />; diff --git a/packages/lib/src/toast/ToastsQueue.tsx b/packages/lib/src/toast/ToastsQueue.tsx index c380f24ece..eb2471c94c 100644 --- a/packages/lib/src/toast/ToastsQueue.tsx +++ b/packages/lib/src/toast/ToastsQueue.tsx @@ -2,7 +2,7 @@ import { useCallback, useEffect, useId, useMemo, useState } from "react"; import { createPortal } from "react-dom"; import styled from "@emotion/styled"; import DxcToast from "./Toast"; -import { QueuedToast, Semantic, ToastsQueuePropsType, ToastType } from "./types"; +import { QueuedToast, Semantic, ToastsQueueProps, ToastType } from "./types"; import { responsiveSizes } from "../common/variables"; import ToastContext from "./ToastContext"; import { generateUniqueToastId } from "./utils"; @@ -25,7 +25,7 @@ const ToastsQueue = styled.section` } `; -export default function DxcToastsQueue({ children, duration = 3000 }: ToastsQueuePropsType) { +export default function DxcToastsQueue({ children, duration = 3000 }: ToastsQueueProps) { const [toasts, setToasts] = useState<QueuedToast[]>([]); const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null); const adjustedDuration = useMemo(() => (duration > 5000 ? 5000 : duration < 3000 ? 3000 : duration), [duration]); diff --git a/packages/lib/src/toast/types.ts b/packages/lib/src/toast/types.ts index 5fdb7363db..49e391d517 100644 --- a/packages/lib/src/toast/types.ts +++ b/packages/lib/src/toast/types.ts @@ -1,5 +1,5 @@ import { ReactNode } from "react"; -import { SVG } from "../common/types"; +import { SVG, PrettifyTypes } from "../common/types"; type Action = { /** @@ -26,35 +26,43 @@ type CommonProps = { */ message: string; }; -type DefaultToast = CommonProps & { - /** - * Material Symbol name or SVG element as the icon that will be placed next to the panel label. - * When using Material Symbols, replace spaces with underscores. - * By default they are outlined if you want it to be filled prefix the symbol name with "filled_". - */ - icon?: string | SVG; -}; -type LoadingToast = CommonProps & { - loading: boolean; -}; -type SemanticToast = CommonProps & { - /** - * Flag that allows to hide the semantic icon of the toast. - */ - hideSemanticIcon?: boolean; -}; +type DefaultToast = PrettifyTypes< + CommonProps & { + /** + * Material Symbol name or SVG element as the icon that will be placed next to the panel label. + * When using Material Symbols, replace spaces with underscores. + * By default they are outlined if you want it to be filled prefix the symbol name with "filled_". + */ + icon?: string | SVG; + } +>; +type LoadingToast = PrettifyTypes< + CommonProps & { + loading: boolean; + } +>; +type SemanticToast = PrettifyTypes< + CommonProps & { + /** + * Flag that allows to hide the semantic icon of the toast. + */ + hideSemanticIcon?: boolean; + } +>; type ToastType = DefaultToast | LoadingToast | SemanticToast; type Semantic = "default" | "info" | "success" | "warning"; -type QueuedToast = ToastType & { - id: string; - semantic: Semantic; -}; +type QueuedToast = PrettifyTypes< + ToastType & { + id: string; + semantic: Semantic; + } +>; -type ToastContextType = (toast: ToastType, semantic: Semantic) => () => void; +type ToastContext = (toast: ToastType, semantic: Semantic) => () => void; -type ToastPropsType = { +type ToastProps = { action?: Action; duration: number; icon?: string | SVG; @@ -65,7 +73,7 @@ type ToastPropsType = { hideSemanticIcon?: boolean; }; -type ToastsQueuePropsType = { +type ToastsQueueProps = { /** * Tree of components from which the useToast hook can be triggered. */ @@ -77,15 +85,15 @@ type ToastsQueuePropsType = { duration?: number; }; -export default ToastPropsType; +export type { ToastProps as default }; export type { - CommonProps, DefaultToast, LoadingToast, QueuedToast, Semantic, SemanticToast, - ToastContextType, - ToastsQueuePropsType, + ToastContext, + ToastsQueueProps, ToastType, + ToastProps, }; diff --git a/packages/lib/src/toast/utils.ts b/packages/lib/src/toast/utils.ts index ac80b9ccb5..b1bfaceb32 100644 --- a/packages/lib/src/toast/utils.ts +++ b/packages/lib/src/toast/utils.ts @@ -1,6 +1,6 @@ -import ToastPropsType, { QueuedToast } from "./types"; +import { ToastProps, QueuedToast } from "./types"; -export default function getSemantic(semantic: ToastPropsType["semantic"]) { +export default function getSemantic(semantic: ToastProps["semantic"]) { switch (semantic) { case "default": return { From 425567ba8ced4f4a209f249a04cfa03a9122e3d6 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Mon, 19 Oct 2026 11:50:56 +0200 Subject: [PATCH 10/18] Last types exported --- packages/lib/src/breadcrumbs/Breadcrumbs.tsx | 6 ++-- packages/lib/src/index.ts | 4 +++ packages/lib/src/toggle-group/ToggleGroup.tsx | 10 +++--- packages/lib/src/toggle-group/types.ts | 34 ++++++++++--------- packages/lib/src/tooltip/Tooltip.tsx | 6 ++-- packages/lib/src/tooltip/types.ts | 4 +-- packages/lib/src/typography/Typography.tsx | 6 ++-- packages/lib/src/typography/types.ts | 6 ++-- packages/lib/src/wizard/Wizard.tsx | 16 ++++----- packages/lib/src/wizard/types.ts | 8 ++--- 10 files changed, 54 insertions(+), 46 deletions(-) diff --git a/packages/lib/src/breadcrumbs/Breadcrumbs.tsx b/packages/lib/src/breadcrumbs/Breadcrumbs.tsx index d1ba3c12e7..cf5c52cae5 100644 --- a/packages/lib/src/breadcrumbs/Breadcrumbs.tsx +++ b/packages/lib/src/breadcrumbs/Breadcrumbs.tsx @@ -4,7 +4,7 @@ import { BreadcrumbsProps } from "./types"; import DxcDropdown from "../dropdown/Dropdown"; import DxcIcon from "../icon/Icon"; import Item from "./Item"; -import { Option } from "../dropdown/types"; +import { DropdownOption } from "../dropdown/types"; import DxcFlex from "../flex/Flex"; const OrderedList = styled.ol` @@ -57,7 +57,9 @@ const DxcBreadcrumbs = ({ icon={<DxcIcon icon="more_horiz" />} margin={showRoot ? { left: "small" } : undefined} onSelectOption={handleOnSelectOption} - options={items.slice(showRoot ? 1 : 0, -1).map(({ label, href }) => ({ label, value: href }) as Option)} + options={items + .slice(showRoot ? 1 : 0, -1) + .map(({ label, href }) => ({ label, value: href }) as DropdownOption)} title="More options" /> </DxcFlex> diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index 02e899ff87..e9533085ea 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -186,3 +186,7 @@ export type { ToastsQueueProps as DxcToastsQueueProps, ToastProps as DxcToastProps, } from "./toast/types"; +export type { ToggleGroupProps as DxcToggleGroupProps, ToggleOption as DxcToggleOption } from "./toggle-group/types"; +export type { TooltipProps as DxcTooltipProps } from "./tooltip/types"; +export type { TypographyProps as DxcTypographyProps } from "./typography/types"; +export type { WizardProps as DxcWizardProps, WizardStepProps as DxcWizardStepProps } from "./wizard/types"; diff --git a/packages/lib/src/toggle-group/ToggleGroup.tsx b/packages/lib/src/toggle-group/ToggleGroup.tsx index ec1ddd85f9..3b90d3c916 100644 --- a/packages/lib/src/toggle-group/ToggleGroup.tsx +++ b/packages/lib/src/toggle-group/ToggleGroup.tsx @@ -3,10 +3,10 @@ import styled from "@emotion/styled"; import { spaces } from "../common/variables"; import DxcIcon from "../icon/Icon"; import { Tooltip } from "../tooltip/Tooltip"; -import ToggleGroupPropsType from "./types"; +import { ToggleGroupProps } from "./types"; import { getButtonStyles, getHeight } from "../button/utils"; -const ToggleGroup = styled.div<{ margin: ToggleGroupPropsType["margin"] }>` +const ToggleGroup = styled.div<{ margin: ToggleGroupProps["margin"] }>` display: flex; &[aria-orientation="vertical"] { flex-direction: column; @@ -51,9 +51,9 @@ const IconContainer = styled.div` `; const isToggleButtonSelected = ( - multiple: ToggleGroupPropsType["multiple"], + multiple: ToggleGroupProps["multiple"], optionValue: number, - value: ToggleGroupPropsType["value"] + value: ToggleGroupProps["value"] ) => (multiple ? Array.isArray(value) && value.includes(optionValue) : optionValue === value); export default function DxcToggleGroup({ @@ -65,7 +65,7 @@ export default function DxcToggleGroup({ orientation = "horizontal", tabIndex = 0, value, -}: ToggleGroupPropsType) { +}: ToggleGroupProps) { const [selectedValue, setSelectedValue] = useState(defaultValue ?? (multiple ? [] : -1)); const handleOnChange = (selectedOption: number) => { diff --git a/packages/lib/src/toggle-group/types.ts b/packages/lib/src/toggle-group/types.ts index f8ddf92056..8746c9c024 100644 --- a/packages/lib/src/toggle-group/types.ts +++ b/packages/lib/src/toggle-group/types.ts @@ -1,6 +1,6 @@ -import { Margin, SVG, Space } from "../common/types"; +import { Margin, PrettifyTypes, SVG, Space } from "../common/types"; -type OptionIcon = { +type ToggleOptionIcon = { /** * Material Symbols icon or SVG element. Icon and label can't be used at same time. */ @@ -16,7 +16,7 @@ type OptionIcon = { title: string; }; -type OptionLabel = { +type ToggleOptionLabel = { /** * Material Symbols icon or SVG element. Icon and label can't be used at same time. */ @@ -32,16 +32,18 @@ type OptionLabel = { title?: never; }; -type Option = { - /** - * If true, the option will be disabled. - */ - disabled?: boolean; - /** - * Number with the option inner value. - */ - value: number; -} & (OptionIcon | OptionLabel); +export type ToggleOption = PrettifyTypes< + { + /** + * If true, the option will be disabled. + */ + disabled?: boolean; + /** + * Number with the option inner value. + */ + value: number; + } & (ToggleOptionIcon | ToggleOptionLabel) +>; type CommonProps = { /** @@ -52,7 +54,7 @@ type CommonProps = { /** * An array of objects representing the selectable options. */ - options: Option[]; + options: ToggleOption[]; /** * The orientation of the toggle group. */ @@ -105,6 +107,6 @@ type SingleSelectionToggleGroup = { value?: number; }; -type Props = CommonProps & (MultipleSelectionToggleGroup | SingleSelectionToggleGroup); +export type ToggleGroupProps = PrettifyTypes<CommonProps & (MultipleSelectionToggleGroup | SingleSelectionToggleGroup)>; -export default Props; +export type { ToggleGroupProps as default }; diff --git a/packages/lib/src/tooltip/Tooltip.tsx b/packages/lib/src/tooltip/Tooltip.tsx index 47d84e4a4c..82c14620f1 100644 --- a/packages/lib/src/tooltip/Tooltip.tsx +++ b/packages/lib/src/tooltip/Tooltip.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; import { cloneElement, isValidElement, use } from "react"; import { Root, Trigger, Portal, Arrow, Content, Provider } from "@radix-ui/react-tooltip"; -import TooltipPropsType, { TooltipWrapperProps } from "./types"; +import { TooltipProps, TooltipWrapperProps } from "./types"; import TooltipContext from "./TooltipContext"; const TooltipTriggerContainer = styled.div` @@ -109,7 +109,7 @@ export const Tooltip = ({ label, position = "bottom", ...rest -}: { hasAdditionalContainer?: boolean } & TooltipPropsType) => { +}: { hasAdditionalContainer?: boolean } & TooltipProps) => { const hasTooltip = use(TooltipContext); return ( <TooltipContext value> @@ -149,6 +149,6 @@ export const TooltipWrapper = ({ condition, children, label, ...rest }: TooltipW children ); -const DxcTooltip = (props: TooltipPropsType) => <Tooltip {...props} hasAdditionalContainer />; +const DxcTooltip = (props: TooltipProps) => <Tooltip {...props} hasAdditionalContainer />; export default DxcTooltip; diff --git a/packages/lib/src/tooltip/types.ts b/packages/lib/src/tooltip/types.ts index c1486a47bd..51d12aa189 100644 --- a/packages/lib/src/tooltip/types.ts +++ b/packages/lib/src/tooltip/types.ts @@ -1,6 +1,6 @@ import { ReactNode } from "react"; -type Props = { +export type TooltipProps = { /** * Content in which the Tooltip will be displayed. */ @@ -21,4 +21,4 @@ export type TooltipWrapperProps = { label?: string; }; -export default Props; +export type { TooltipProps as default }; diff --git a/packages/lib/src/typography/Typography.tsx b/packages/lib/src/typography/Typography.tsx index 27faa1a763..a07f2ee147 100644 --- a/packages/lib/src/typography/Typography.tsx +++ b/packages/lib/src/typography/Typography.tsx @@ -1,9 +1,9 @@ import { use, useMemo } from "react"; import styled from "@emotion/styled"; -import TypographyPropsTypes from "./types"; +import { TypographyProps } from "./types"; import TypographyContext from "./TypographyContext"; -const Typography = styled.span<TypographyPropsTypes>` +const Typography = styled.span<TypographyProps>` margin: 0px; display: ${({ display }) => display}; color: ${({ color }) => color}; @@ -21,7 +21,7 @@ const Typography = styled.span<TypographyPropsTypes>` overflow: ${({ textOverflow }) => (textOverflow !== "unset" ? "hidden" : "visible")}; `; -export default function DxcTypography({ children, ...props }: TypographyPropsTypes) { +export default function DxcTypography({ children, ...props }: TypographyProps) { const componentContext = use(TypographyContext); const contextValue = useMemo( diff --git a/packages/lib/src/typography/types.ts b/packages/lib/src/typography/types.ts index d88b56257d..44ec517d26 100644 --- a/packages/lib/src/typography/types.ts +++ b/packages/lib/src/typography/types.ts @@ -1,6 +1,6 @@ import { ReactNode } from "react"; -export type Props = { +export type TypographyProps = { as?: | "a" | "blockquote" @@ -35,6 +35,6 @@ export type Props = { whiteSpace?: "normal" | "nowrap" | "pre" | "pre-line" | "pre-wrap"; }; -export type TypographyContextProps = Required<Omit<Props, "children">>; +export type TypographyContextProps = Required<Omit<TypographyProps, "children">>; -export default Props; +export type { TypographyProps as default }; diff --git a/packages/lib/src/wizard/Wizard.tsx b/packages/lib/src/wizard/Wizard.tsx index fb0799b368..adae5a97a0 100644 --- a/packages/lib/src/wizard/Wizard.tsx +++ b/packages/lib/src/wizard/Wizard.tsx @@ -3,14 +3,14 @@ import styled from "@emotion/styled"; import { spaces } from "../common/variables"; import DxcDivider from "../divider/Divider"; import DxcIcon from "../icon/Icon"; -import WizardPropsType, { StepProps } from "./types"; +import { WizardProps, WizardStepProps } from "./types"; import DxcFlex from "../flex/Flex"; import icons from "./Icons"; import { css } from "@emotion/react"; const Wizard = styled.div<{ - margin: WizardPropsType["margin"]; - mode: WizardPropsType["mode"]; + margin: WizardProps["margin"]; + mode: WizardProps["mode"]; }>` display: flex; flex-direction: ${({ mode }) => (mode === "vertical" ? "column" : "row")}; @@ -26,7 +26,7 @@ const Wizard = styled.div<{ const StepContainer = styled.div<{ lastStep: boolean; - mode: WizardPropsType["mode"]; + mode: WizardProps["mode"]; }>` flex-grow: ${({ lastStep }) => (lastStep ? "0" : "1")}; display: grid; @@ -35,7 +35,7 @@ const StepContainer = styled.div<{ const IconContainer = styled.div<{ current: boolean; - disabled: StepProps["disabled"]; + disabled: WizardStepProps["disabled"]; visited: boolean; }>` box-sizing: border-box; @@ -76,7 +76,7 @@ const Description = styled.span` `; const Step = styled.button<{ - mode: WizardPropsType["mode"]; + mode: WizardProps["mode"]; unvisited: boolean; }>` display: flex; @@ -155,7 +155,7 @@ const ValidityIconContainer = styled.div<{ disabled?: boolean; valid: boolean }> } `; -const DividerContainer = styled.div<{ mode: WizardPropsType["mode"] }>` +const DividerContainer = styled.div<{ mode: WizardProps["mode"] }>` display: grid; place-items: center; ${({ mode }) => mode === "vertical" && "width: 32px"}; @@ -169,7 +169,7 @@ export default function DxcWizard({ onStepClick, steps, tabIndex = 0, -}: WizardPropsType) { +}: WizardProps) { const [innerCurrent, setInnerCurrentStep] = useState(defaultCurrentStep); const handleStepOnClick = (newValue: number) => { diff --git a/packages/lib/src/wizard/types.ts b/packages/lib/src/wizard/types.ts index 97621ea1f2..73b6fe0f90 100644 --- a/packages/lib/src/wizard/types.ts +++ b/packages/lib/src/wizard/types.ts @@ -1,6 +1,6 @@ import { Margin, SVG, Space } from "../common/types"; -export type StepProps = { +export type WizardStepProps = { /** * Step label. */ @@ -23,7 +23,7 @@ export type StepProps = { valid?: boolean; }; -type Props = { +export type WizardProps = { /** * The wizard can be shown in horizontal or vertical. */ @@ -44,7 +44,7 @@ type Props = { /** * An array of objects representing the steps. */ - steps: StepProps[]; + steps: WizardStepProps[]; /** * Size of the margin to be applied to the component ('xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge'). * You can pass an object with 'top', 'bottom', 'left' and 'right' properties in order to specify different margin sizes. @@ -56,4 +56,4 @@ type Props = { tabIndex?: number; }; -export default Props; +export type { WizardProps as default }; From 04a4768df1632e0e35c0d2d72d2c5ad0c43abb4e Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Mon, 19 Oct 2026 14:46:40 +0200 Subject: [PATCH 11/18] tokens exported and base menu types improved --- packages/lib/src/base-menu/types.ts | 26 +++++++++++++++----------- packages/lib/src/index.ts | 2 ++ packages/lib/src/styles/tokens.ts | 4 ++-- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/lib/src/base-menu/types.ts b/packages/lib/src/base-menu/types.ts index c8da76d92a..e7700e20a4 100644 --- a/packages/lib/src/base-menu/types.ts +++ b/packages/lib/src/base-menu/types.ts @@ -1,5 +1,5 @@ import { ButtonHTMLAttributes, Dispatch, ReactElement, ReactNode, SetStateAction } from "react"; -import { SVG } from "../common/types"; +import { PrettifyTypes, SVG } from "../common/types"; type BaseCommonItemProps = { badge?: ReactElement; @@ -7,17 +7,21 @@ type BaseCommonItemProps = { label: string; }; -type BaseItem = BaseCommonItemProps & { - onSelect?: () => void; - selected?: boolean; - href?: string; - renderItem?: (props: { children: ReactNode }) => ReactNode; -}; +type BaseItem = PrettifyTypes< + BaseCommonItemProps & { + onSelect?: () => void; + selected?: boolean; + href?: string; + renderItem?: (props: { children: ReactNode }) => ReactNode; + } +>; -type BaseGroupItem = BaseCommonItemProps & { - items: (BaseItem | BaseGroupItem)[]; - defaultOpen?: boolean; -}; +type BaseGroupItem = PrettifyTypes< + BaseCommonItemProps & { + items: (BaseItem | BaseGroupItem)[]; + defaultOpen?: boolean; + } +>; type BaseSection = { items: (BaseItem | BaseGroupItem)[]; title?: string }; type BaseMenuProps = { /** diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index e9533085ea..b21991d771 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -56,6 +56,8 @@ export { default as DxcWizard } from "./wizard/Wizard"; export { HalstackProvider, HalstackLanguageContext } from "./HalstackContext"; export { default as useToast } from "./toast/useToast"; +export { coreTokens as DxcCoreTokens, aliasTokens as DxcAliasTokens } from "./styles/tokens"; + // types exports export type { Action as DxcAction, diff --git a/packages/lib/src/styles/tokens.ts b/packages/lib/src/styles/tokens.ts index f5face5beb..910f17978d 100644 --- a/packages/lib/src/styles/tokens.ts +++ b/packages/lib/src/styles/tokens.ts @@ -1,4 +1,4 @@ -export const coreTokens: Record<string, string | number> = { +export const coreTokens = { /**************/ /** POSITION **/ /**************/ @@ -168,7 +168,7 @@ export const coreTokens: Record<string, string | number> = { "--line-style-solid": "solid", }; -export const aliasTokens: Record<string, string | number> = { +export const aliasTokens = { /************/ /** TOKENS **/ /************/ From 459f2b80e4f17fdc23c3ee07a618fa51cd8ad4e6 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Mon, 19 Oct 2026 14:49:21 +0200 Subject: [PATCH 12/18] Website lib typings imports fixed --- apps/website/pages/_app.tsx | 15 ++++++++------- apps/website/screens/common/pagesList.tsx | 6 +++--- .../overview/MessageInputOverviewPage.tsx | 4 +--- .../foundations/tokens/tables/TokensTable.tsx | 9 +++++++-- .../cloudscapeGuidelinesSection.tsx | 3 +-- .../previews/components/DataGridPreview.tsx | 4 ++-- .../previews/examples/ApplicationPreview.tsx | 4 ++-- .../theme-generator/steps/BrandingDetails.tsx | 4 ++-- apps/website/tsconfig.json | 2 +- 9 files changed, 27 insertions(+), 24 deletions(-) diff --git a/apps/website/pages/_app.tsx b/apps/website/pages/_app.tsx index a00a12b6d8..8325d771f6 100644 --- a/apps/website/pages/_app.tsx +++ b/apps/website/pages/_app.tsx @@ -11,8 +11,7 @@ import "../global-styles.css"; import createCache, { EmotionCache } from "@emotion/cache"; import { CacheProvider } from "@emotion/react"; import Link from "next/link"; -import { GroupItem, Item, Section } from "../../../packages/lib/src/base-menu/types"; -import { isGroupItem } from "../../../packages/lib/src/base-menu/utils"; +import { DxcBaseGroupItem, DxcBaseItem, DxcBaseSection } from "@dxc-technology/halstack-react"; import SidenavLogo from "@/common/sidenav/SidenavLogo"; import { dxcLogo } from "@/common/images/dxc_logo"; @@ -24,6 +23,8 @@ type AppPropsWithLayout = AppProps & { emotionCache?: EmotionCache; }; +export const isGroupItem = (item: DxcBaseItem | DxcBaseGroupItem): item is DxcBaseGroupItem => "items" in item; + const clientSideEmotionCache = createCache({ key: "css", prepend: true }); export default function App({ Component, pageProps, emotionCache = clientSideEmotionCache }: AppPropsWithLayout) { @@ -39,7 +40,7 @@ export default function App({ Component, pageProps, emotionCache = clientSideEmo return pathToBeMatched ? desiredPaths.includes(pathToBeMatched) : false; }; - const createNavItem = (link: LinkDetails): Item => ({ + const createNavItem = (link: LinkDetails): DxcBaseItem => ({ label: link.label, href: link.path, selected: matchPaths(link.path), @@ -52,7 +53,7 @@ export default function App({ Component, pageProps, emotionCache = clientSideEmo ), }); - const normalizeNavTabs = (links: (LinkDetails | LinksSectionDetails)[]): (Item | GroupItem)[] => { + const normalizeNavTabs = (links: (LinkDetails | LinksSectionDetails)[]): (DxcBaseItem | DxcBaseGroupItem)[] => { return links.map((link) => { if ("links" in link) { return { @@ -66,8 +67,8 @@ export default function App({ Component, pageProps, emotionCache = clientSideEmo }); }; - const filterNavTree = (items: (Item | GroupItem)[], q: string): (Item | GroupItem)[] => { - const result: (Item | GroupItem)[] = []; + const filterNavTree = (items: (DxcBaseItem | DxcBaseGroupItem)[], q: string): (DxcBaseItem | DxcBaseGroupItem)[] => { + const result: (DxcBaseItem | DxcBaseGroupItem)[] = []; for (const item of items) { if (isGroupItem(item)) { @@ -87,7 +88,7 @@ export default function App({ Component, pageProps, emotionCache = clientSideEmo return result; }; - const navItems: Section[] = useMemo(() => { + const navItems: DxcBaseSection[] = useMemo(() => { const q = filter.trim().toLowerCase(); return LinksSections.map((section) => { diff --git a/apps/website/screens/common/pagesList.tsx b/apps/website/screens/common/pagesList.tsx index 59a58c4ae1..8a5341d47e 100644 --- a/apps/website/screens/common/pagesList.tsx +++ b/apps/website/screens/common/pagesList.tsx @@ -1,4 +1,4 @@ -import { SVG } from "../../../../packages/lib/src/common/utils"; +import type { DxcSVG } from "@dxc-technology/halstack-react"; import componentsList from "./componentsList.json"; export type ComponentStatus = "experimental" | "new" | "stable" | "legacy" | "deprecated"; @@ -7,13 +7,13 @@ export type LinkDetails = { label: string; path: string; status?: ComponentStatus; - icon?: string | SVG; + icon?: string | DxcSVG; }; export type LinksSectionDetails = { label: string; links: (LinkDetails | LinksSectionDetails)[]; - icon?: string | SVG; + icon?: string | DxcSVG; }; type NavigationLinks = { diff --git a/apps/website/screens/components/message-input/overview/MessageInputOverviewPage.tsx b/apps/website/screens/components/message-input/overview/MessageInputOverviewPage.tsx index 4bed803f27..d301b0cb91 100644 --- a/apps/website/screens/components/message-input/overview/MessageInputOverviewPage.tsx +++ b/apps/website/screens/components/message-input/overview/MessageInputOverviewPage.tsx @@ -1,8 +1,6 @@ import QuickNavContainer from "@/common/QuickNavContainer"; -import DxcFlex from "../../../../../../packages/lib/src/flex/Flex"; import DocFooter from "@/common/DocFooter"; -import DxcParagraph from "../../../../../../packages/lib/src/paragraph/Paragraph"; -import { DxcBulletedList } from "@dxc-technology/halstack-react"; +import { DxcBulletedList, DxcParagraph, DxcFlex } from "@dxc-technology/halstack-react"; import Figure from "@/common/Figure"; import Image from "@/common/Image"; import messageInputAnatomy from "./images/message-input-anatomy.png"; diff --git a/apps/website/screens/foundations/tokens/tables/TokensTable.tsx b/apps/website/screens/foundations/tokens/tables/TokensTable.tsx index 968632bf5c..e878376b49 100644 --- a/apps/website/screens/foundations/tokens/tables/TokensTable.tsx +++ b/apps/website/screens/foundations/tokens/tables/TokensTable.tsx @@ -1,6 +1,6 @@ import { TableCode } from "@/common/Code"; import { DxcTable } from "@dxc-technology/halstack-react"; -import { aliasTokens, coreTokens } from "../../../../../../packages/lib/src/styles/tokens"; +import { DxcAliasTokens, DxcCoreTokens } from "@dxc-technology/halstack-react"; import getTokensByCategory from "./utils/mapCategory"; const TokensTable = ({ categories, type }: { categories: string[]; type: "alias" | "core" }) => ( @@ -12,7 +12,12 @@ const TokensTable = ({ categories, type }: { categories: string[]; type: "alias" </tr> </thead> <tbody> - {getTokensByCategory(type === "alias" ? aliasTokens : coreTokens, categories).map(([token, value]) => ( + {getTokensByCategory( + type === "alias" + ? (DxcAliasTokens as Record<string, string | number>) + : (DxcCoreTokens as Record<string, string | number>), + categories + ).map(([token, value]) => ( <tr key={token}> <td> <TableCode>{token}</TableCode> diff --git a/apps/website/screens/guidelines/data-visualization/cloudscapeGuidelinesSection.tsx b/apps/website/screens/guidelines/data-visualization/cloudscapeGuidelinesSection.tsx index c45cdd470f..2f7daad074 100644 --- a/apps/website/screens/guidelines/data-visualization/cloudscapeGuidelinesSection.tsx +++ b/apps/website/screens/guidelines/data-visualization/cloudscapeGuidelinesSection.tsx @@ -1,7 +1,6 @@ import { SectionType } from "@/common/Section"; -import DxcParagraph from "../../../../../packages/lib/src/paragraph/Paragraph"; import Link from "next/link"; -import { DxcBulletedList, DxcFlex, DxcLink } from "@dxc-technology/halstack-react"; +import { DxcBulletedList, DxcParagraph, DxcFlex, DxcLink } from "@dxc-technology/halstack-react"; import Image from "@/common/Image"; import cloudscapeBarImage from "./images/cloudscape_bar_chart.png"; import cloudscapePieImage from "./images/cloudscape_pie_chart.png"; diff --git a/apps/website/screens/theme-generator/previews/components/DataGridPreview.tsx b/apps/website/screens/theme-generator/previews/components/DataGridPreview.tsx index a56008bbcd..2138b4fde1 100644 --- a/apps/website/screens/theme-generator/previews/components/DataGridPreview.tsx +++ b/apps/website/screens/theme-generator/previews/components/DataGridPreview.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; import { DxcDataGrid, DxcContainer } from "@dxc-technology/halstack-react"; -import type { GridColumn } from "../../../../../../packages/lib/src/data-grid/types"; +import type { DxcDataGridColumn } from "@dxc-technology/halstack-react"; const actions = [ { @@ -16,7 +16,7 @@ const actions = [ }, ]; -const columns: GridColumn[] = [ +const columns: DxcDataGridColumn[] = [ { key: "id", label: "ID", diff --git a/apps/website/screens/theme-generator/previews/examples/ApplicationPreview.tsx b/apps/website/screens/theme-generator/previews/examples/ApplicationPreview.tsx index 4634a6a0db..e3a7c93866 100644 --- a/apps/website/screens/theme-generator/previews/examples/ApplicationPreview.tsx +++ b/apps/website/screens/theme-generator/previews/examples/ApplicationPreview.tsx @@ -13,7 +13,7 @@ import { DxcInset, } from "@dxc-technology/halstack-react"; import { Logos } from "screens/theme-generator/types"; -import { GridRow } from "../../../../../../packages/lib/src/data-grid/types"; +import type { DxcDataGridRow } from "@dxc-technology/halstack-react"; const columnsDatagrid = [ { @@ -348,7 +348,7 @@ const ApplicationPreview = ({ logos }: { logos: Logos }) => { </DxcFlex> <DxcDataGrid columns={columnsDatagrid} - rows={rowsDatagrid as GridRow[]} + rows={rowsDatagrid as DxcDataGridRow[]} uniqueRowId="policyId" selectable selectedRows={selectedRows} diff --git a/apps/website/screens/theme-generator/steps/BrandingDetails.tsx b/apps/website/screens/theme-generator/steps/BrandingDetails.tsx index 9593bb6f8b..d0ca89beb9 100644 --- a/apps/website/screens/theme-generator/steps/BrandingDetails.tsx +++ b/apps/website/screens/theme-generator/steps/BrandingDetails.tsx @@ -1,5 +1,5 @@ import { DxcContainer, DxcFlex } from "@dxc-technology/halstack-react"; -import { FileData } from "../../../../../packages/lib/src/file-input/types"; +import type { DxcFileData } from "@dxc-technology/halstack-react"; import { Colors, Logos } from "../types"; import BrandingLogoGrid from "../components/branding/BrandingLogoGrid"; import { brandingIcon, infoIcon, paletteIcon } from "./icons"; @@ -63,7 +63,7 @@ const BrandingDetails = ({ }); }; - const updateLogoValue = (logoType: string, files: FileData[]) => { + const updateLogoValue = (logoType: string, files: DxcFileData[]) => { onLogosChange({ ...logos, [logoType]: files, diff --git a/apps/website/tsconfig.json b/apps/website/tsconfig.json index 20d99ca6e6..ba2885ac0c 100644 --- a/apps/website/tsconfig.json +++ b/apps/website/tsconfig.json @@ -9,6 +9,6 @@ "@/common/*": ["screens/common/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "next.config.ts", "test", "../../packages/lib/src/**/*.d.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "next.config.ts", "test"], "exclude": ["node_modules", "out", ".turbo", ".next"] } From 512a47edea8a0599410a441e814731a395514860 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Mon, 19 Oct 2026 16:21:35 +0200 Subject: [PATCH 13/18] Contextual types mistmatch fixed --- packages/lib/src/contextual-menu/ContextualMenu.tsx | 6 +++--- packages/lib/src/contextual-menu/ContextualMenuContext.tsx | 4 ---- packages/lib/src/contextual-menu/types.ts | 5 ++--- 3 files changed, 5 insertions(+), 10 deletions(-) delete mode 100644 packages/lib/src/contextual-menu/ContextualMenuContext.tsx diff --git a/packages/lib/src/contextual-menu/ContextualMenu.tsx b/packages/lib/src/contextual-menu/ContextualMenu.tsx index c34e8eef23..65a24d6694 100644 --- a/packages/lib/src/contextual-menu/ContextualMenu.tsx +++ b/packages/lib/src/contextual-menu/ContextualMenu.tsx @@ -3,7 +3,7 @@ import styled from "@emotion/styled"; import MenuItem from "../base-menu/MenuItem"; import Section from "../base-menu/Section"; import SubMenu from "../base-menu/SubMenu"; -import ContextualMenuContext from "./ContextualMenuContext"; +import BaseMenuContext from "../base-menu/BaseMenuContext"; import { ContextualMenuProps } from "./types"; import scrollbarStyles from "../styles/scroll"; import { addIdToItems, isSection } from "../base-menu/utils"; @@ -47,7 +47,7 @@ export default function DxcContextualMenu({ items }: ContextualMenuProps) { return ( <ContextualMenu ref={contextualMenuRef}> - <ContextualMenuContext value={contextValue}> + <BaseMenuContext value={contextValue}> {itemsWithId[0] && isSection(itemsWithId[0]) ? ( (itemsWithId as BaseSectionWithId[]).map((item, index) => ( <Section key={`section-${index}`} section={item} index={index} length={itemsWithId.length} /> @@ -59,7 +59,7 @@ export default function DxcContextualMenu({ items }: ContextualMenuProps) { ))} </SubMenu> )} - </ContextualMenuContext> + </BaseMenuContext> </ContextualMenu> ); } diff --git a/packages/lib/src/contextual-menu/ContextualMenuContext.tsx b/packages/lib/src/contextual-menu/ContextualMenuContext.tsx deleted file mode 100644 index 767f9f8513..0000000000 --- a/packages/lib/src/contextual-menu/ContextualMenuContext.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { createContext } from "react"; -import { ContextualMenuContextProps } from "./types"; - -export default createContext<ContextualMenuContextProps | null>(null); diff --git a/packages/lib/src/contextual-menu/types.ts b/packages/lib/src/contextual-menu/types.ts index 2bd21d1dcc..fbab2476c4 100644 --- a/packages/lib/src/contextual-menu/types.ts +++ b/packages/lib/src/contextual-menu/types.ts @@ -1,9 +1,8 @@ -import BaseProps, { BaseMenuContextProps } from "../base-menu/types"; +import BaseProps from "../base-menu/types"; type ContextualMenuProps = Omit< BaseProps, "displayBorder" | "displayGroupLines" | "displayControlsAfter" | "hasPopOver" >; -type ContextualMenuContextProps = Omit<BaseMenuContextProps, "hasPopOver">; -export type { ContextualMenuProps, ContextualMenuContextProps, ContextualMenuProps as default }; +export type { ContextualMenuProps, ContextualMenuProps as default }; From 20fe3f92263ceeda295cf35690497d26bdc3224a Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Wed, 21 Oct 2026 09:46:22 +0200 Subject: [PATCH 14/18] Missing bleed and divider exports in index --- packages/lib/src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index b21991d771..065f887b4d 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -90,6 +90,7 @@ export type { BaseGroupItem as DxcBaseGroupItem, BaseSection as DxcBaseSection, } from "./base-menu/types"; +export type { BleedProps as DxcBleedProps } from "./bleed/types"; export type { BreadcrumbsProps as DxcBreadcrumbsProps, BreadcrumbsItemProps as DxcBreadcrumbsItemProps, @@ -121,6 +122,7 @@ export type { } from "./data-grid/types"; export type { DateInputProps as DxcDateInputProps } from "./date-input/types"; export type { DialogProps as DxcDialogProps } from "./dialog/types"; +export type { DividerProps as DxcDividerProps } from "./divider/types"; export type { DropdownProps as DxcDropdownProps, DropdownOption as DxcDropdownOption } from "./dropdown/types"; export type { FileInputProps as DxcFileInputProps, FileData as DxcFileData } from "./file-input/types"; export type { FlexProps as DxcFlexProps } from "./flex/types"; From 4b4c6a2b176bd151bc4df379b4bb855f44095981 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Wed, 21 Oct 2026 10:12:35 +0200 Subject: [PATCH 15/18] Added some missing exports --- packages/lib/src/container/types.ts | 40 ++++++++++++++--------------- packages/lib/src/data-grid/types.ts | 7 ++--- packages/lib/src/index.ts | 15 ++++++++++- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/packages/lib/src/container/types.ts b/packages/lib/src/container/types.ts index 847e906620..4683d8bdd8 100644 --- a/packages/lib/src/container/types.ts +++ b/packages/lib/src/container/types.ts @@ -1,14 +1,14 @@ import { ReactNode, Ref } from "react"; import { PrettifyTypes } from "../common/types"; -export type Spacing = { +export type ContainerSpacing = { top?: string; right?: string; bottom?: string; left?: string; }; -export type Background = { +export type ContainerBackground = { attachment?: string; clip?: string; color?: string; @@ -19,29 +19,29 @@ export type Background = { size?: string; }; -export type BorderProperties = { +export type ContainerBorderProperties = { width?: string; style?: string; color?: string; }; -export type Border = PrettifyTypes< - | BorderProperties +export type ContainerBorder = PrettifyTypes< + | ContainerBorderProperties | { - top?: BorderProperties; - right?: BorderProperties; - bottom?: BorderProperties; - left?: BorderProperties; + top?: ContainerBorderProperties; + right?: ContainerBorderProperties; + bottom?: ContainerBorderProperties; + left?: ContainerBorderProperties; } >; -export type Outline = PrettifyTypes< - BorderProperties & { +export type ContainerOutline = PrettifyTypes< + ContainerBorderProperties & { offset?: string; } >; export type OverflowValues = "visible" | "hidden" | "clip" | "scroll" | "auto"; -export type Overflow = PrettifyTypes<OverflowValues | { x?: OverflowValues; y?: OverflowValues }>; +export type ContainerOverflow = PrettifyTypes<OverflowValues | { x?: OverflowValues; y?: OverflowValues }>; export type ContainerProps = { /** @@ -49,11 +49,11 @@ export type ContainerProps = { * * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/background */ - background?: Background; + background?: ContainerBackground; /** * Based on the CSS property border allows configuring all properties related to the border of a container. */ - border?: Border; + border?: ContainerBorder; /** * Sets the border-radius CSS property. * @@ -105,11 +105,11 @@ export type ContainerProps = { * Based on the CSS property inset this prop is a shorthand that corresponds * to the top, right, bottom, and/or left properties. */ - inset?: Spacing; + inset?: ContainerSpacing; /** * Size of the margin to be applied to the container. */ - margin?: string | Spacing; + margin?: string | ContainerSpacing; /** * Sets the max-width CSS property. * @@ -138,17 +138,17 @@ export type ContainerProps = { * Based on the CSS property outline allows configuring all properties related * to the outline of a container. */ - outline?: Outline; + outline?: ContainerOutline; /** * Sets the overflow CSS property. * * See MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/overflow */ - overflow?: Overflow; + overflow?: ContainerOverflow; /** * Size of the padding to be applied to the container. */ - padding?: string | Spacing; + padding?: string | ContainerSpacing; /** * Sets the position CSS property. * @@ -172,7 +172,7 @@ export type ContainerProps = { export type StyledProps = Omit<ContainerProps, "display" | "width" | "height" | "opacity" | "overflow"> & { $display?: "block" | "inline-block" | "inline" | "none"; $height?: string; - $overflow?: Overflow; + $overflow?: ContainerOverflow; $width?: string; }; diff --git a/packages/lib/src/data-grid/types.ts b/packages/lib/src/data-grid/types.ts index 013e8d3be9..0ec2f6795c 100644 --- a/packages/lib/src/data-grid/types.ts +++ b/packages/lib/src/data-grid/types.ts @@ -240,11 +240,8 @@ type DataGridBasicProps = { type DataGridProps = PrettifyTypes< CommonProps & (DataGridPaginatedProps | DataGridNonPaginatedProps) & - ( - | (DataGridBasicProps & DataGridSelectableProps) - | (DataGridExpandableRows & DataGridSelectableProps) - | (DataGridHierarchyRows & DataGridSelectableProps) - ) + (DataGridBasicProps | DataGridExpandableRows | DataGridHierarchyRows) & + DataGridSelectableProps >; export type { diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index 065f887b4d..2628b14db5 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -108,6 +108,15 @@ export type { export type { CardProps as DxcCardProps } from "./card/types"; export type { CheckboxProps as DxcCheckboxProps } from "./checkbox/types"; export type { ChipProps as DxcChipProps } from "./chip/types"; +export type { + ContainerProps as DxcContainerProps, + ContainerSpacing as DxcContainerSpacing, + ContainerBackground as DxcContainerBackground, + ContainerBorderProperties as DxcContainerBorderProperties, + ContainerBorder as DxcContainerBorder, + ContainerOutline as DxcContainerOutline, + ContainerOverflow as DxcOverflow, +} from "./container/types"; export type { ContextualMenuProps as DxcContextualMenuProps } from "./contextual-menu/types"; export type { DataGridProps as DxcDataGridProps, @@ -125,7 +134,7 @@ export type { DialogProps as DxcDialogProps } from "./dialog/types"; export type { DividerProps as DxcDividerProps } from "./divider/types"; export type { DropdownProps as DxcDropdownProps, DropdownOption as DxcDropdownOption } from "./dropdown/types"; export type { FileInputProps as DxcFileInputProps, FileData as DxcFileData } from "./file-input/types"; -export type { FlexProps as DxcFlexProps } from "./flex/types"; +export type { FlexProps as DxcFlexProps, FlexGap as DxcFlexGap } from "./flex/types"; export type { FooterProps as DxcFooterProps, FooterBottomLink as DxcFooterBottomLink, @@ -156,6 +165,9 @@ export type { NavTabsProps as DxcNavTabsProps, NavTabsTabProps as DxcNavTabsTabP export type { NumberInputProps as DxcNumberInputProps } from "./number-input/types"; export type { PaginatorProps as DxcPaginatorProps } from "./paginator/types"; export type { PasswordInputProps as DxcPasswordInputProps } from "./password-input/types"; +export type { PopoverProps as DxcPopoverProps } from "./popover/types"; +export type { ProgressBarProps as DxcProgressBarProps } from "./progress-bar/types"; +export type { QuickNavProps as DxcQuickNavProps, QuickNavLink as DxcQuickNavLink } from "./quick-nav/types"; export type { RadioGroupProps as DxcRadioGroupProps, RadioGroupOption as DxcRadioGroupOption, @@ -183,6 +195,7 @@ export type { TableProps as DxcTableProps, ActionsCellProps as DxcActionsCellPro export type { TabsProps as DxcTabsProps, TabsTabProps as DxcTabsTabProps } from "./tabs/types"; export type { TextInputProps as DxcTextInputProps } from "./text-input/types"; export type { TextAreaProps as DxcTextareaProps } from "./textarea/types"; +export type { TimeInputProps as DxcTimeInputProps } from "./time-input/types"; export type { DefaultToast as DxcDefaultToast, LoadingToast as DxcLoadingToast, From f90b75bb5a1f2a7ece3575ad3346770bea789598 Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Wed, 21 Oct 2026 10:20:11 +0200 Subject: [PATCH 16/18] Fix build failing due to type renamed --- packages/lib/src/container/Container.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lib/src/container/Container.tsx b/packages/lib/src/container/Container.tsx index 0fb1103a41..779811dcf1 100644 --- a/packages/lib/src/container/Container.tsx +++ b/packages/lib/src/container/Container.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; -import { BorderProperties, StyledProps, ContainerProps } from "./types"; +import { ContainerBorderProperties, StyledProps, ContainerProps } from "./types"; -const getBorderStyles = (direction: "top" | "bottom" | "left" | "right", borderProperties: BorderProperties) => +const getBorderStyles = (direction: "top" | "bottom" | "left" | "right", borderProperties: ContainerBorderProperties) => `border-${direction}: ${borderProperties.width ?? ""} ${borderProperties.style ?? ""} ${ borderProperties.color ?? "" };`; From 8d7d1144121534b2c01df8980a4cedf5a885d14c Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Wed, 21 Oct 2026 16:48:53 +0200 Subject: [PATCH 17/18] Fixed type issues found in review --- .../lib/src/data-grid/DataGrid.stories.tsx | 26 +++++++++---------- .../lib/src/dropdown/Dropdown.stories.tsx | 8 +++--- packages/lib/src/dropdown/types.ts | 2 +- packages/lib/src/grid/types.ts | 7 ++--- packages/lib/src/header/Header.test.tsx | 6 ++--- packages/lib/src/header/types.ts | 4 +-- packages/lib/src/index.ts | 4 +-- packages/lib/src/status-light/StatusLight.tsx | 18 ++++++------- packages/lib/src/tabs/utils.ts | 6 ++--- packages/lib/src/toast/ToastContext.tsx | 4 +-- packages/lib/src/toast/types.ts | 4 +-- 11 files changed, 45 insertions(+), 44 deletions(-) diff --git a/packages/lib/src/data-grid/DataGrid.stories.tsx b/packages/lib/src/data-grid/DataGrid.stories.tsx index 4d8b10d15c..dc25a1b521 100644 --- a/packages/lib/src/data-grid/DataGrid.stories.tsx +++ b/packages/lib/src/data-grid/DataGrid.stories.tsx @@ -4,10 +4,10 @@ import ExampleContainer from "../../.storybook/components/ExampleContainer"; import DxcDataGrid from "./DataGrid"; import DxcContainer from "../container/Container"; import disabledRules from "../../test/accessibility/rules/specific/data-grid/disabledRules"; -import { GridColumn, HierarchyGridRow } from "./types"; +import { DataGridColumn, DataGridHierarchyRow } from "./types"; import preview from "../../.storybook/preview"; import DxcBadge from "../badge/Badge"; -import { ActionsCellPropsType } from "../table/types"; +import { ActionsCellProps } from "../table/types"; import { isKeyOfRow } from "./utils"; import { Meta, StoryObj } from "@storybook/react-vite"; import { userEvent, within } from "storybook/test"; @@ -27,7 +27,7 @@ export default { }, } satisfies Meta<typeof DxcDataGrid>; -const actions: ActionsCellPropsType["actions"] = [ +const actions: ActionsCellProps["actions"] = [ { title: "icon", onClick: (value?) => { @@ -102,7 +102,7 @@ const actions: ActionsCellPropsType["actions"] = [ }, ]; -const columns: GridColumn[] = [ +const columns: DataGridColumn[] = [ { key: "id", label: "ID", @@ -306,7 +306,7 @@ const expandableRowsPaginated = [ }, ]; -const childcolumns: GridColumn[] = [ +const childcolumns: DataGridColumn[] = [ { key: "name", label: "Name", @@ -442,11 +442,11 @@ const childRows = [ }, ], }, -] as HierarchyGridRow[]; +] as DataGridHierarchyRow[]; -const childrenTrigger = (open: boolean, triggerRow: HierarchyGridRow) => { +const childrenTrigger = (open: boolean, triggerRow: DataGridHierarchyRow) => { if (open) { - return new Promise<HierarchyGridRow[]>((resolve) => { + return new Promise<DataGridHierarchyRow[]>((resolve) => { setTimeout(() => { resolve([ { @@ -461,11 +461,11 @@ const childrenTrigger = (open: boolean, triggerRow: HierarchyGridRow) => { id: `${triggerRow.id as string}-child-2`, childrenTrigger, }, - ] as unknown as HierarchyGridRow[]); + ] as unknown as DataGridHierarchyRow[]); }, 5000); }); } else { - return [] as HierarchyGridRow[]; + return [] as DataGridHierarchyRow[]; } }; @@ -494,7 +494,7 @@ const childRowsLazy = [ id: "lazy-d", childrenTrigger, }, -] as unknown as HierarchyGridRow[]; +] as unknown as DataGridHierarchyRow[]; const childRowsPaginated = [ { @@ -613,9 +613,9 @@ const childRowsPaginated = [ }, ], }, -] as HierarchyGridRow[]; +] as DataGridHierarchyRow[]; -const customSortColumns: GridColumn[] = [ +const customSortColumns: DataGridColumn[] = [ { key: "id", label: "ID", diff --git a/packages/lib/src/dropdown/Dropdown.stories.tsx b/packages/lib/src/dropdown/Dropdown.stories.tsx index 6fdb2bac84..005b5e33b7 100644 --- a/packages/lib/src/dropdown/Dropdown.stories.tsx +++ b/packages/lib/src/dropdown/Dropdown.stories.tsx @@ -3,7 +3,7 @@ import Title from "../../.storybook/components/Title"; import disabledRules from "../../test/accessibility/rules/specific/dropdown/disabledRules"; import DxcDropdown from "./Dropdown"; import DropdownMenu from "./DropdownMenu"; -import { Option } from "./types"; +import { DropdownOption } from "./types"; import preview from "../../.storybook/preview"; import { Meta, StoryObj } from "@storybook/react-vite"; import { userEvent, within } from "storybook/test"; @@ -36,7 +36,7 @@ const iconSVGLarge = ( ); const icons = [iconSVG, iconSVGLarge, "nutrition"]; -const defaultOptions: Option[] = [ +const defaultOptions: DropdownOption[] = [ { value: "1", label: "Amazon", @@ -72,7 +72,7 @@ const defaultOptions: Option[] = [ label: "Gearbest shop", }, ]; -const options: Option[] = [ +const options: DropdownOption[] = [ { value: "1", label: "Amazon with a very long text", @@ -87,7 +87,7 @@ const options: Option[] = [ label: "Apple", }, ]; -const optionWithIcon: Option[] = [ +const optionWithIcon: DropdownOption[] = [ { value: "1", label: "Ebay", diff --git a/packages/lib/src/dropdown/types.ts b/packages/lib/src/dropdown/types.ts index 889eed06a0..2eac294959 100644 --- a/packages/lib/src/dropdown/types.ts +++ b/packages/lib/src/dropdown/types.ts @@ -88,7 +88,7 @@ export type DropdownMenuProps = { menuItemOnClick: (value: string) => void; onKeyDown: (event: KeyboardEvent<HTMLUListElement>) => void; options: DropdownOption[]; - ref: React.Ref<HTMLUListElement>; + ref?: React.Ref<HTMLUListElement>; styles: CSSProperties; }; diff --git a/packages/lib/src/grid/types.ts b/packages/lib/src/grid/types.ts index c692c16e7c..34f18c481e 100644 --- a/packages/lib/src/grid/types.ts +++ b/packages/lib/src/grid/types.ts @@ -8,11 +8,12 @@ type GridPlaceContentValues = "baseline" | "center" | "end" | "normal" | "space-around" | "space-between" | "space-evenly" | "start" | "stretch"; type GridPlaceItemsValues = "baseline" | "center" | "end" | "normal" | "start" | "stretch"; type PlaceObject<Type, Suffix extends string> = { - [Property in Extract<keyof Type, string> as `${Property}${Capitalize<Suffix>}`]: Type[Property]; + [Property in keyof Type as Property extends string ? `${Property}${Capitalize<Suffix>}` : never]: Type[Property]; }; + type PlaceGeneric<PlaceValues, Element extends string> = - | PlaceObject<{ align: PlaceValues; justify?: PlaceValues }, Element> - | PlaceObject<{ align?: PlaceValues; justify: PlaceValues }, Element> + | PlaceObject<{ align?: PlaceValues; justify?: PlaceValues }, Element> + | PlaceObject<{ align: PlaceValues; justify: PlaceValues }, Element> | PlaceValues; type GridItemProps = { diff --git a/packages/lib/src/header/Header.test.tsx b/packages/lib/src/header/Header.test.tsx index 760a591d6f..3e4e294a00 100644 --- a/packages/lib/src/header/Header.test.tsx +++ b/packages/lib/src/header/Header.test.tsx @@ -1,7 +1,7 @@ import { render, screen, fireEvent } from "@testing-library/react"; import "@testing-library/jest-dom"; import DxcHeader from "./Header"; -import { Item, GroupItem } from "../base-menu/types"; +import { BaseItem, BaseGroupItem } from "../base-menu/types"; describe("Header component tests", () => { const mockMatchMedia = jest.fn(); @@ -52,7 +52,7 @@ describe("Header component tests", () => { removeEventListener: jest.fn(), })); - const navItems: Item[] = [{ label: "Home", onSelect: jest.fn() }]; + const navItems: BaseItem[] = [{ label: "Home", onSelect: jest.fn() }]; render(<DxcHeader navItems={navItems} />); const menuButton = screen.getByRole("button", { name: /toggle menu/i }); @@ -61,7 +61,7 @@ describe("Header component tests", () => { }); test("handles nested group items beyond LEVEL_LIMIT (should be ignored)", () => { - const deepNestedItems: (Item | GroupItem)[] = [ + const deepNestedItems: (BaseItem | BaseGroupItem)[] = [ { label: "Services", items: [ diff --git a/packages/lib/src/header/types.ts b/packages/lib/src/header/types.ts index 64e46f9bff..427552e1f8 100644 --- a/packages/lib/src/header/types.ts +++ b/packages/lib/src/header/types.ts @@ -9,13 +9,13 @@ export type HeaderGroupItem = PrettifyTypes< } >; -export type HeaderMainNavPropsType = (HeaderGroupItem | PrettifyTypes<BaseItem>)[]; +export type HeaderMainNavProps = (HeaderGroupItem | PrettifyTypes<BaseItem>)[]; export type HeaderSearchBarProps = Omit<SearchBarProps, "autoFocus" | "disabled">; export type HeaderProps = { appTitle?: string; - navItems?: HeaderMainNavPropsType; + navItems?: HeaderMainNavProps; responsiveBottomContent?: ReactNode; searchBar?: HeaderSearchBarProps; sideContent?: ReactNode | ((isResponsive: boolean) => ReactNode); diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts index 2628b14db5..3d943d9b86 100644 --- a/packages/lib/src/index.ts +++ b/packages/lib/src/index.ts @@ -115,7 +115,7 @@ export type { ContainerBorderProperties as DxcContainerBorderProperties, ContainerBorder as DxcContainerBorder, ContainerOutline as DxcContainerOutline, - ContainerOverflow as DxcOverflow, + ContainerOverflow as DxcContainerOverflow, } from "./container/types"; export type { ContextualMenuProps as DxcContextualMenuProps } from "./contextual-menu/types"; export type { @@ -152,7 +152,7 @@ export type { } from "./grid/types"; export type { HeaderProps as DxcHeaderProps, - HeaderMainNavPropsType as DxcHeaderMainNavPropsType, + HeaderMainNavProps as DxcHeaderMainNavProps, HeaderSearchBarProps as DxcHeaderSearchBarProps, HeaderGroupItem as DxcHeaderGroupItem, } from "./header/types"; diff --git a/packages/lib/src/status-light/StatusLight.tsx b/packages/lib/src/status-light/StatusLight.tsx index 1e4f7b6c86..7b1d000caf 100644 --- a/packages/lib/src/status-light/StatusLight.tsx +++ b/packages/lib/src/status-light/StatusLight.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; -import iStatusLightProps from "./types"; +import { StatusLightProps } from "./types"; -const getModeColor = (mode: Required<iStatusLightProps>["mode"]) => { +const getModeColor = (mode: Required<StatusLightProps>["mode"]) => { switch (mode) { case "default": return "var(--color-fg-neutral-strong);"; @@ -16,7 +16,7 @@ const getModeColor = (mode: Required<iStatusLightProps>["mode"]) => { } }; -const getSizeValues = (size: Required<iStatusLightProps>["size"]) => { +const getSizeValues = (size: Required<StatusLightProps>["size"]) => { switch (size) { case "small": return { @@ -36,7 +36,7 @@ const getSizeValues = (size: Required<iStatusLightProps>["size"]) => { } }; -const StatusLightContainer = styled.div<{ size: Required<iStatusLightProps>["size"] }>` +const StatusLightContainer = styled.div<{ size: Required<StatusLightProps>["size"] }>` display: inline-flex; align-items: center; gap: ${({ size }) => (size === "small" ? "var(--spacing-gap-xs)" : "var(--spacing-gap-s)")}; @@ -44,8 +44,8 @@ const StatusLightContainer = styled.div<{ size: Required<iStatusLightProps>["siz `; const Dot = styled.div<{ - mode: Required<iStatusLightProps>["mode"]; - size: Required<iStatusLightProps>["size"]; + mode: Required<StatusLightProps>["mode"]; + size: Required<StatusLightProps>["size"]; }>` background-color: ${({ mode }) => getModeColor(mode)}; border-radius: 50%; @@ -55,8 +55,8 @@ const Dot = styled.div<{ `; const Label = styled.span<{ - mode: Required<iStatusLightProps>["mode"]; - size: Required<iStatusLightProps>["size"]; + mode: Required<StatusLightProps>["mode"]; + size: Required<StatusLightProps>["size"]; }>` color: ${({ mode }) => getModeColor(mode)}; font-family: var(--typography-font-family); @@ -67,7 +67,7 @@ const Label = styled.span<{ white-space: nowrap; `; -export default function DxcStatusLight({ label, mode = "default", size = "medium" }: iStatusLightProps) { +export default function DxcStatusLight({ label, mode = "default", size = "medium" }: StatusLightProps) { return ( <StatusLightContainer role="status" size={size}> <Dot mode={mode} size={size} aria-hidden="true" /> diff --git a/packages/lib/src/tabs/utils.ts b/packages/lib/src/tabs/utils.ts index 428da17890..d31679d7d9 100644 --- a/packages/lib/src/tabs/utils.ts +++ b/packages/lib/src/tabs/utils.ts @@ -1,7 +1,7 @@ import { ReactElement } from "react"; -import { TabProps } from "./types"; +import { TabsTabProps } from "./types"; -export const getNextTabIndex = (array: ReactElement<TabProps>[], initialIndex: number): number => { +export const getNextTabIndex = (array: ReactElement<TabsTabProps>[], initialIndex: number): number => { let index = initialIndex === array.length - 1 ? 0 : initialIndex + 1; while (array[index]?.props.disabled) { index = index === array.length - 1 ? 0 : index + 1; @@ -9,7 +9,7 @@ export const getNextTabIndex = (array: ReactElement<TabProps>[], initialIndex: n return index; }; -export const getPreviousTabIndex = (array: ReactElement<TabProps>[], initialIndex: number): number => { +export const getPreviousTabIndex = (array: ReactElement<TabsTabProps>[], initialIndex: number): number => { let index = initialIndex === 0 ? array.length - 1 : initialIndex - 1; while (array[index]?.props.disabled) { index = index === 0 ? array.length - 1 : index - 1; diff --git a/packages/lib/src/toast/ToastContext.tsx b/packages/lib/src/toast/ToastContext.tsx index 1c239254a6..e4f07e111a 100644 --- a/packages/lib/src/toast/ToastContext.tsx +++ b/packages/lib/src/toast/ToastContext.tsx @@ -1,4 +1,4 @@ import { createContext } from "react"; -import { ToastContext } from "./types"; +import { ToastContextType } from "./types"; -export default createContext<ToastContext | null>(null); +export default createContext<ToastContextType | null>(null); diff --git a/packages/lib/src/toast/types.ts b/packages/lib/src/toast/types.ts index 49e391d517..e98452cbdb 100644 --- a/packages/lib/src/toast/types.ts +++ b/packages/lib/src/toast/types.ts @@ -60,7 +60,7 @@ type QueuedToast = PrettifyTypes< } >; -type ToastContext = (toast: ToastType, semantic: Semantic) => () => void; +type ToastContextType = (toast: ToastType, semantic: Semantic) => () => void; type ToastProps = { action?: Action; @@ -92,7 +92,7 @@ export type { QueuedToast, Semantic, SemanticToast, - ToastContext, + ToastContextType, ToastsQueueProps, ToastType, ToastProps, From 5a3b76796e2402ae1065d0cb96d41178256d7eaf Mon Sep 17 00:00:00 2001 From: jialecl <jialestrabajos@gmail.com> Date: Thu, 22 Oct 2026 09:17:38 +0200 Subject: [PATCH 18/18] Wrong imports in DataGrid tests fixed --- packages/lib/src/data-grid/DataGrid.test.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/lib/src/data-grid/DataGrid.test.tsx b/packages/lib/src/data-grid/DataGrid.test.tsx index 94f37f6f27..0c03c8ace9 100644 --- a/packages/lib/src/data-grid/DataGrid.test.tsx +++ b/packages/lib/src/data-grid/DataGrid.test.tsx @@ -1,6 +1,6 @@ import { fireEvent, render } from "@testing-library/react"; import DxcDataGrid from "./DataGrid"; -import { GridColumn, HierarchyGridRow } from "./types"; +import { DataGridColumn, DataGridHierarchyRow } from "./types"; Object.defineProperty(window, "getComputedStyle", { value: () => ({ @@ -18,7 +18,7 @@ global.ResizeObserver = jest.fn().mockImplementation(() => ({ disconnect: jest.fn(), })); -const columns: GridColumn[] = [ +const columns: DataGridColumn[] = [ { key: "id", label: "ID", @@ -64,7 +64,7 @@ const expandableRows = [ }, ]; -const hierarchyRows: HierarchyGridRow[] = [ +const hierarchyRows: DataGridHierarchyRow[] = [ { name: "Root Node 1", value: "1", @@ -210,7 +210,7 @@ const hierarchyRows: HierarchyGridRow[] = [ }, ], }, -] as HierarchyGridRow[]; +] as DataGridHierarchyRow[]; const loadedChildrenMock = [ { id: "child-1", name: "Child 1", value: "Child 1" }, @@ -219,7 +219,7 @@ const loadedChildrenMock = [ const childrenTriggerMock = jest.fn().mockResolvedValue(loadedChildrenMock); -const hierarchyRowsLazy: HierarchyGridRow[] = [ +const hierarchyRowsLazy: DataGridHierarchyRow[] = [ { name: "Root Node 1 Lazy", value: "1", @@ -246,7 +246,7 @@ const hierarchyRowsLazy: HierarchyGridRow[] = [ value: "5", id: "lazy-e", }, -] as HierarchyGridRow[]; +] as DataGridHierarchyRow[]; describe("Data grid component tests", () => { beforeAll(() => {