diff --git a/README.md b/README.md index 10d8826fa5..085c047e23 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ const App = () => ( ## Where to start -Learn everything you need to know about Halstack principles and components on the [official documentation site](https://developer.assure.dxc.com/halstack/). +Learn everything you need to know about Halstack guidelines and components on the [official documentation site](https://developer.assure.dxc.com/halstack/). ## Contributing diff --git a/apps/website/hooks/useCopyToClipboard.tsx b/apps/website/hooks/useCopyToClipboard.tsx new file mode 100644 index 0000000000..27d6fe3256 --- /dev/null +++ b/apps/website/hooks/useCopyToClipboard.tsx @@ -0,0 +1,20 @@ +import { useToast } from "@dxc-technology/halstack-react"; + +const useCopyToClipboard = () => { + const toast = useToast(); + + const handleCopy = (text: string) => { + navigator.clipboard + .writeText(text) + .then(() => { + toast.success({ message: "Code copied to the clipboard." }); + }) + .catch(() => { + toast.warning({ message: "Failed to copy the text to the clipboard." }); + }); + }; + + return handleCopy; +}; + +export default useCopyToClipboard; diff --git a/apps/website/package.json b/apps/website/package.json index a8b1b81a09..fb434a125f 100644 --- a/apps/website/package.json +++ b/apps/website/package.json @@ -8,6 +8,7 @@ "lint": "eslint . --max-warnings 0" }, "dependencies": { + "@adobe/leonardo-contrast-colors": "^1.0.0", "@cloudscape-design/components": "^3.0.706", "@dxc-technology/halstack-react": "*", "@emotion/cache": "^11.14.0", diff --git a/apps/website/pages/_app.tsx b/apps/website/pages/_app.tsx index fdffe9c9a5..942240c825 100644 --- a/apps/website/pages/_app.tsx +++ b/apps/website/pages/_app.tsx @@ -2,7 +2,7 @@ import { ReactElement, ReactNode, useMemo, useState } from "react"; import type { NextPage } from "next"; import type { AppProps } from "next/app"; import Head from "next/head"; -import { DxcApplicationLayout, DxcToastsQueue } from "@dxc-technology/halstack-react"; +import { DxcApplicationLayout, DxcInset, DxcLink, DxcToastsQueue } from "@dxc-technology/halstack-react"; import MainContent from "@/common/MainContent"; import { useRouter } from "next/router"; import { LinkDetails, LinksSectionDetails, LinksSections } from "@/common/pagesList"; @@ -31,6 +31,7 @@ export default function App({ Component, pageProps, emotionCache = clientSideEmo const componentWithLayout = getLayout(); const [filter, setFilter] = useState(""); const { asPath: currentPath } = useRouter(); + const isThemeGenerator = currentPath.includes("/theme-generator"); const matchPaths = (linkPath: string) => { const desiredPaths = [linkPath, `${linkPath}/code`]; @@ -109,18 +110,40 @@ export default function App({ Component, pageProps, emotionCache = clientSideEmo } + header={ + isThemeGenerator ? ( + + + + User guide + + + + ) + } + /> + ) : ( + + ) + } sidenav={ - } - searchBar={{ placeholder: "Search docs", onChange: (value) => setFilter(value) }} - /> + !isThemeGenerator && ( + } + searchBar={{ placeholder: "Search docs", onChange: (value) => setFilter(value) }} + /> + ) } + footer={isThemeGenerator ? : undefined} > - {componentWithLayout} + {!isThemeGenerator ? {componentWithLayout} : <>{componentWithLayout}} diff --git a/apps/website/pages/principles/data-visualization.tsx b/apps/website/pages/guidelines/data-visualization.tsx similarity index 80% rename from apps/website/pages/principles/data-visualization.tsx rename to apps/website/pages/guidelines/data-visualization.tsx index 8958669537..cbb9c4367c 100644 --- a/apps/website/pages/principles/data-visualization.tsx +++ b/apps/website/pages/guidelines/data-visualization.tsx @@ -1,5 +1,5 @@ import Head from "next/head"; -import DataVisualizationPage from "screens/principles/data-visualization/DataVisualizationPage"; +import DataVisualizationPage from "screens/guidelines/data-visualization/DataVisualizationPage"; const DataVisualization = () => ( <> diff --git a/apps/website/pages/principles/localization.tsx b/apps/website/pages/guidelines/localization.tsx similarity index 78% rename from apps/website/pages/principles/localization.tsx rename to apps/website/pages/guidelines/localization.tsx index 70bba38057..39653ad2af 100644 --- a/apps/website/pages/principles/localization.tsx +++ b/apps/website/pages/guidelines/localization.tsx @@ -1,5 +1,5 @@ import Head from "next/head"; -import LocalizationPage from "screens/principles/localization/LocalizationPage"; +import LocalizationPage from "screens/guidelines/localization/LocalizationPage"; const Localization = () => ( <> diff --git a/apps/website/pages/guidelines/themes.tsx b/apps/website/pages/guidelines/themes.tsx new file mode 100644 index 0000000000..500f50bb14 --- /dev/null +++ b/apps/website/pages/guidelines/themes.tsx @@ -0,0 +1,13 @@ +import Head from "next/head"; +import ThemesPage from "screens/guidelines/themes/ThemesPage"; + +const Themes = () => ( + <> + + Themes — Halstack Design System + + + +); + +export default Themes; diff --git a/apps/website/pages/theme-generator/configuration.tsx b/apps/website/pages/theme-generator/configuration.tsx new file mode 100644 index 0000000000..9d37a727ac --- /dev/null +++ b/apps/website/pages/theme-generator/configuration.tsx @@ -0,0 +1,15 @@ +import Head from "next/head"; +import ThemeGeneratorConfigPage from "screens/theme-generator/ThemeGeneratorConfigPage"; + +const Index = () => { + return ( + <> + + Theme generator — Halstack Design System + + + + ); +}; + +export default Index; diff --git a/apps/website/pages/theme-generator/index.tsx b/apps/website/pages/theme-generator/index.tsx new file mode 100644 index 0000000000..d5a0415ac1 --- /dev/null +++ b/apps/website/pages/theme-generator/index.tsx @@ -0,0 +1,15 @@ +import Head from "next/head"; +import ThemeGeneratorPage from "screens/theme-generator/ThemeGeneratorPage"; + +const Index = () => { + return ( + <> + + Theme generator — Halstack Design System + + + + ); +}; + +export default Index; diff --git a/apps/website/pages/theme-generator/user-guide.tsx b/apps/website/pages/theme-generator/user-guide.tsx new file mode 100644 index 0000000000..8f5dc57375 --- /dev/null +++ b/apps/website/pages/theme-generator/user-guide.tsx @@ -0,0 +1,15 @@ +import Head from "next/head"; +import ThemeGeneratorUserGuidePage from "screens/theme-generator/ThemeGeneratorUserGuidePage"; + +const Index = () => { + return ( + <> + + Theme generator — Halstack Design System + + + + ); +}; + +export default Index; diff --git a/apps/website/public/dxc_footer_logo.svg b/apps/website/public/dxc_footer_logo.svg deleted file mode 100644 index 522bab5a75..0000000000 --- a/apps/website/public/dxc_footer_logo.svg +++ /dev/null @@ -1,32 +0,0 @@ - - DXC Logo - - - - - - - - - - - - - - \ No newline at end of file diff --git a/apps/website/public/dxc_header_logo.svg b/apps/website/public/dxc_header_logo.svg deleted file mode 100644 index b98a0044d5..0000000000 --- a/apps/website/public/dxc_header_logo.svg +++ /dev/null @@ -1,13 +0,0 @@ - - DXC Logo - - - - - - - \ No newline at end of file diff --git a/apps/website/public/theme-generator-landing-bg-flipped.png b/apps/website/public/theme-generator-landing-bg-flipped.png new file mode 100644 index 0000000000..16550d1260 Binary files /dev/null and b/apps/website/public/theme-generator-landing-bg-flipped.png differ diff --git a/apps/website/public/theme-generator-landing-bg.png b/apps/website/public/theme-generator-landing-bg.png new file mode 100644 index 0000000000..3fe470b74b Binary files /dev/null and b/apps/website/public/theme-generator-landing-bg.png differ diff --git a/apps/website/screens/common/example/Example.tsx b/apps/website/screens/common/example/Example.tsx index 23970f0030..afdc75dd42 100644 --- a/apps/website/screens/common/example/Example.tsx +++ b/apps/website/screens/common/example/Example.tsx @@ -2,7 +2,8 @@ import { useState } from "react"; import styled from "@emotion/styled"; import { LiveProvider, LiveEditor, LiveError, LivePreview } from "react-live"; import theme from "./liveEditorTheme"; -import { DxcButton, DxcFlex, useToast } from "@dxc-technology/halstack-react"; +import { DxcButton, DxcFlex } from "@dxc-technology/halstack-react"; +import useCopyToClipboard from "hooks/useCopyToClipboard"; const StyledPreview = styled.div` background-color: var(--color-bg-neutral-lightest); @@ -49,24 +50,13 @@ type ExamplePropTypes = { }; // const Example = ({ actionsVisible = true, defaultIsVisible = false, example }: ExamplePropTypes) => { - const toast = useToast(); const [isCodeVisible, changeIsCodeVisible] = useState(defaultIsVisible); const [liveCode, setLiveCode] = useState(example.code); const handleCodeOnClick = () => { changeIsCodeVisible(!isCodeVisible); }; - - const handleCopy = () => { - navigator.clipboard - .writeText(liveCode) - .then(() => { - toast.success({ message: "Code copied to the clipboard." }); - }) - .catch(() => { - toast.warning({ message: "Failed to copy the text to the clipboard." }); - }); - }; + const handleCopy = useCopyToClipboard(); return ( @@ -79,7 +69,16 @@ const Example = ({ actionsVisible = true, defaultIsVisible = false, example }: E {actionsVisible && ( - {isCodeVisible && } + {isCodeVisible && ( + { + handleCopy(liveCode); + }} + /> + )} - DXC Logo - - - - - - + + Expand commentComment on line R9Resolved + + + + + + + + + + + ); diff --git a/apps/website/screens/common/pagesList.tsx b/apps/website/screens/common/pagesList.tsx index 32f1f9f99d..59a58c4ae1 100644 --- a/apps/website/screens/common/pagesList.tsx +++ b/apps/website/screens/common/pagesList.tsx @@ -36,9 +36,10 @@ const utilitiesLinks: LinkDetails[] = [ }, ]; -const principlesLinks: LinkDetails[] = [ - { label: "Data visualization", path: "/principles/data-visualization", icon: "insert_chart" }, - { label: "Localization", path: "/principles/localization", icon: "language" }, +const guidelinesLinks: LinkDetails[] = [ + { label: "Data visualization", path: "/guidelines/data-visualization", icon: "insert_chart" }, + { label: "Localization", path: "/guidelines/localization", icon: "language" }, + { label: "Themes", path: "/guidelines/themes", icon: "colors" }, ]; const tokensLinks: LinkDetails[] = [ @@ -70,7 +71,7 @@ const componentsLinks = componentsList as (LinkDetails | LinksSectionDetails)[]; export const LinksSections: LinksSectionDetails[] = [ { label: "Overview", links: overviewLinks }, - { label: "Principles", links: principlesLinks }, + { label: "Guidelines", links: guidelinesLinks }, { label: "Foundations", links: foundationsLinks }, { label: "Migration", links: migrationLinks }, { label: "Utilities", links: utilitiesLinks }, diff --git a/apps/website/screens/components/quick-nav/code/examples/quickNav.tsx b/apps/website/screens/components/quick-nav/code/examples/quickNav.tsx index 436ca2def1..a01d75a611 100644 --- a/apps/website/screens/components/quick-nav/code/examples/quickNav.tsx +++ b/apps/website/screens/components/quick-nav/code/examples/quickNav.tsx @@ -6,7 +6,7 @@ const code = `() => { label: "Overview", }, { - label: "Principles", + label: "Foundations", links: [ { label: "Color" }, { label: "Spacing" }, diff --git a/apps/website/screens/principles/data-visualization/DataVisualizationPage.tsx b/apps/website/screens/guidelines/data-visualization/DataVisualizationPage.tsx similarity index 100% rename from apps/website/screens/principles/data-visualization/DataVisualizationPage.tsx rename to apps/website/screens/guidelines/data-visualization/DataVisualizationPage.tsx diff --git a/apps/website/screens/principles/data-visualization/examples/barChart.tsx b/apps/website/screens/guidelines/data-visualization/examples/barChart.tsx similarity index 100% rename from apps/website/screens/principles/data-visualization/examples/barChart.tsx rename to apps/website/screens/guidelines/data-visualization/examples/barChart.tsx diff --git a/apps/website/screens/principles/data-visualization/images/bar_chart_color_palette.png b/apps/website/screens/guidelines/data-visualization/images/bar_chart_color_palette.png similarity index 100% rename from apps/website/screens/principles/data-visualization/images/bar_chart_color_palette.png rename to apps/website/screens/guidelines/data-visualization/images/bar_chart_color_palette.png diff --git a/apps/website/screens/principles/data-visualization/images/bar_chart_variants.png b/apps/website/screens/guidelines/data-visualization/images/bar_chart_variants.png similarity index 100% rename from apps/website/screens/principles/data-visualization/images/bar_chart_variants.png rename to apps/website/screens/guidelines/data-visualization/images/bar_chart_variants.png diff --git a/apps/website/screens/principles/localization/LocalizationPage.tsx b/apps/website/screens/guidelines/localization/LocalizationPage.tsx similarity index 100% rename from apps/website/screens/principles/localization/LocalizationPage.tsx rename to apps/website/screens/guidelines/localization/LocalizationPage.tsx diff --git a/apps/website/screens/principles/localization/examples/translations.tsx b/apps/website/screens/guidelines/localization/examples/translations.tsx similarity index 100% rename from apps/website/screens/principles/localization/examples/translations.tsx rename to apps/website/screens/guidelines/localization/examples/translations.tsx diff --git a/apps/website/screens/guidelines/themes/ThemesPage.tsx b/apps/website/screens/guidelines/themes/ThemesPage.tsx new file mode 100644 index 0000000000..fb8809ca0f --- /dev/null +++ b/apps/website/screens/guidelines/themes/ThemesPage.tsx @@ -0,0 +1,153 @@ +import DocFooter from "@/common/DocFooter"; +import PageHeading from "@/common/PageHeading"; +import DxcQuickNavContainer from "@/common/QuickNavContainer"; +import { DxcAlert, DxcBulletedList, DxcFlex, DxcHeading, DxcLink, DxcParagraph } from "@dxc-technology/halstack-react"; +import Link from "next/link"; + +const sections = [ + { + title: "What is a theme in Halstack?", + content: ( + <> + + In Halstack, a theme is a structured set of properties that defines how your brand is + expressed across the design system. These properties allow you to adapt core visual decisions such as colors + and logos, while preserving the consistency, accessibility, and usability standards defined by Halstack. + + + To understand what a theme is, it is important to recognize that the definition of colors, sizes, shapes, and + visual foundations is an intrinsic part of any design system. These elements are carefully designed to ensure + accessibility, usability, and a consistent user experience. For this reason, changing them must be done in a + controlled and intentional way. + + + Themes provide this controlled flexibility. They allow teams to override specific foundational decisions of + the Halstack Design System in order to adapt product to different brand identities, while still benefiting + from the structure and scalability of the system. + + + ), + }, + { + title: "Why themes matter?", + content: ( + <> + + Color, branding, and visual identity{" "} + play a key role in how users perceive and interact with a product. A consistent and + accessible visual language helps guide user behavior, improves readability, and strengthens trust. + + + However, unmanaged customization can quickly lead to fragmentation, accessibility issues, and higher + maintenance costs. Themes help prevent this by offering a structured way to evolve brand identity without + breaking the foundations of the design system. They support scalability, maintain accessibility, and enable + consistency across products, teams, and client implementations. + + + Typically, teams build their applications using the default Halstack foundations. Themes are applied only when + there is a clear need to adapt the experience to a specific brand, such as in white-label or multi-brand + environments. In this way, theming remains intentional and aligned with product and business needs. + + + ), + }, + { + title: "How Halstack manages theming", + content: ( + <> + + Halstack approaches theming through design tokens. Instead of manually adjusting styles in + each component, you define a set of core and semantic values that are applied across the system. + + The main customizable aspects include: + + + Core brand colors such as primary, secondary, tertiary, and neutral + + + Semantic colors such as info, success, warning, and error + + + Brand assets such as logos and favicons + + + + This approach ensures that customization remains predictable, accessible, and easy to maintain over time. + + + ), + }, + { + title: "Where to manage your themes", + content: ( + + To create and manage themes in Halstack, you can use the Theme Generator tool. You can preview how your theme + behaves across real Halstack components, validate contrast and readability, and export a structured file ready + to be integrated into your project. + + ), + }, + { + title: "Introducing Theme Generator", + content: ( + <> + + + + Theme Generator + + {" "} + helps you create Halstack themes without manual token configuration. Instead of defining dozens of values, you + provide your core and semantic colors, and the tool generates a complete, ready-to-use token structure. + + + You can also preview how your theme behaves in real Halstack components and layouts, validate contrast and + readability, and export a structured file ready to be integrated into your development workflow. + + + This enables designers and developers to collaborate around a shared and repeatable process, ensuring + consistency across products and brands. + + + For more details about how the tool works, visit the{" "} + + + Theme Generator user guide + + + . + + + ), + }, +]; + +const ThemesPage = () => ( + + + + + + You can start configuring your own themes using the{" "} + + + Theme Generator + + + + ), + }} + /> + + + + + +); + +export default ThemesPage; diff --git a/apps/website/screens/overview/installation/InstallationPage.tsx b/apps/website/screens/overview/installation/InstallationPage.tsx index 757f227a04..bdc2276248 100644 --- a/apps/website/screens/overview/installation/InstallationPage.tsx +++ b/apps/website/screens/overview/installation/InstallationPage.tsx @@ -88,7 +88,7 @@ const sections = [ title: "What's next?", content: ( - Before you continue developing your project with Halstack, we encourage you to read our principles. This will + Before you continue developing your project with Halstack, we encourage you to read our guidelines. This will help you understand the design foundations behind the components and how to use them effectively. ), diff --git a/apps/website/screens/theme-generator/ThemeGeneratorConfigPage.tsx b/apps/website/screens/theme-generator/ThemeGeneratorConfigPage.tsx new file mode 100644 index 0000000000..28342182c8 --- /dev/null +++ b/apps/website/screens/theme-generator/ThemeGeneratorConfigPage.tsx @@ -0,0 +1,154 @@ +import { useMemo, useRef, useState } from "react"; +import { DxcContainer, DxcFlex, DxcWizard } from "@dxc-technology/halstack-react"; +import StepHeading from "./components/StepHeading"; +import BottomButtons from "./components/BottomButtons"; +import ThemeGeneratorPreviewPage from "./ThemeGeneratorPreviewPage"; +// import { FileData } from "../../../../packages/lib/src/file-input/types"; + +import { BrandingDetails } from "./steps/BrandingDetails"; +import { generateTokens, handleExport } from "./utils"; +import { Colors, FileData, Step } from "./types"; +import ReviewDetails from "./steps/ReviewDetails"; + +const steps = [ + { + label: "Configure theme", + description: "Branding details", + title: "Add your theme specifics", + subtitle: "Review your uploaded theme or define your brand colors and logos to preview them in real life. ", + }, + { + label: "Preview", + description: "Components and templates", + title: "Preview how your theme applies", + subtitle: "Choose components or examples from Halstack catalogue to see how your theme behaves.", + }, + { + label: "Export theme", + description: "Review and export", + title: "Review and export your theme", + subtitle: "Check your colors and branding assets before exporting your Halstack theme.", + }, +] as const; + +const wizardSteps = steps.map(({ label, description }) => ({ + label, + description, +})); + +const ThemeGeneratorConfigPage = () => { + const [currentStep, setCurrentStep] = useState(0); + const [colors, setColors] = useState({ + primary: "#5F249F", + secondary: "#0067B3", + tertiary: "#F7CF2B", + neutral: "#999999", + info: "#0067B3", + success: "#59D97D", + error: "#FE344F", + warning: "#F59F3D", + }); + const [logos, setLogos] = useState({ + mainLogo: [] as FileData[], + footerLogo: [] as FileData[], + footerReducedLogo: [] as FileData[], + favicon: [] as FileData[], + }); + const [tokens, setTokens] = useState>({}); + const lastGeneratedColorsRef = useRef(""); + + const themeJson = useMemo(() => { + const themeObject = { + tokens: tokens, + logos: { + mainLogo: "", + footerLogo: "", + footerReducedLogo: "", + favicon: "", + }, + }; + return JSON.stringify(themeObject, null, 2); + }, [tokens]); + + const generateTokensFromColors = () => { + try { + const mappedColors = { + primary: colors.primary, + secondary: colors.secondary, + tertiary: colors.tertiary, + semantic01: colors.info, + semantic02: colors.success, + semantic03: colors.warning, + semantic04: colors.error, + neutral: colors.neutral, + }; + + const generatedTokens = generateTokens(mappedColors); + + setTokens(generatedTokens); + lastGeneratedColorsRef.current = JSON.stringify(colors); + } catch (error) { + console.error("Error generating tokens:", error); + } + }; + + const handleChangeStep = (step: 0 | 1 | 2) => { + if (currentStep === 0 && JSON.stringify(colors) !== lastGeneratedColorsRef.current) { + generateTokensFromColors(); + } + setCurrentStep(step); + }; + + const renderStepContent = () => { + switch (currentStep) { + case 0: + return ; + case 1: + return ; + case 2: + return ; + } + }; + + return ( + + + + { + handleChangeStep(i as Step); + }} + /> + + + + + + {renderStepContent()} + + + + handleExport(themeJson)} + /> + + + ); +}; + +export default ThemeGeneratorConfigPage; diff --git a/apps/website/screens/theme-generator/ThemeGeneratorPage.tsx b/apps/website/screens/theme-generator/ThemeGeneratorPage.tsx new file mode 100644 index 0000000000..a2d9df2e0d --- /dev/null +++ b/apps/website/screens/theme-generator/ThemeGeneratorPage.tsx @@ -0,0 +1,156 @@ +import { + DxcLink, + DxcContainer, + DxcFlex, + DxcHeading, + DxcTypography, + DxcParagraph, + DxcInset, + DxcGrid, +} from "@dxc-technology/halstack-react"; +import Link from "next/link"; +import LandingCards from "./components/LandingCards"; +import LandingSteps from "./components/LandingSteps"; + +const steps = [ + { + title: "Define your brand", + description: "Choose your core and semantic colors to set the foundation of your theme.", + }, + { + title: "Let the system do the rest", + description: "The generator creates a complete set of tokens based on your colors.", + }, + { + title: "See it in real components", + description: "Preview your theme applied to real Halstack components and layouts.", + }, + { + title: "Export and use it", + description: "Review your theme and export it as a ready-to-use JSON file.", + }, +]; + +const cards = [ + { + icon: "filled_palette", + title: "From brand colors to design tokens", + description: "Define your core and semantic colors and let the generator create a structured set of design tokens.", + }, + { + icon: "preview", + title: "Preview your theme in real components", + description: + "Apply your generated tokens to real Halstack components and layouts to validate your color choices in context.", + }, + { + icon: "accessibility", + title: "Accessible and ready to implement", + description: + "The generator adjusts color combinations to aim for strong contrast and readability. Export a ready-to-use theme file and integrate it into your development workflow.", + }, +]; + +const ThemeGeneratorPage = () => { + return ( + <> + + + + + + + + + Create and explore your brand within Halstack. Configure your core colors, upload your logo + variants, and see in real time how your theme works across components, layouts, and real product + scenarios. + + + + + + Start your theme + + + + + + + + + + + + + + Theme Generator removes the complexity of brand customization so your team can move + faster, stay consistent, and ship with confidence. + + + + + + + + + + + From brand colors to a production-ready Halstack theme in just a few clear steps. + + + + + + + + Your brand, fully expressed in Halstack + + + + + Turn your brand into a living part of your products. Keep every interface aligned, consistent, and + easier to evolve as your needs grow. + + + + + + + + Open Theme Generator + + + + View documentation + + + + + + ); +}; +export default ThemeGeneratorPage; diff --git a/apps/website/screens/theme-generator/ThemeGeneratorPreviewPage.tsx b/apps/website/screens/theme-generator/ThemeGeneratorPreviewPage.tsx new file mode 100644 index 0000000000..00a9c1961a --- /dev/null +++ b/apps/website/screens/theme-generator/ThemeGeneratorPreviewPage.tsx @@ -0,0 +1,276 @@ +import { + DxcButton, + DxcContainer, + DxcFlex, + DxcSelect, + DxcToggleGroup, + DxcTypography, + HalstackProvider, +} from "@dxc-technology/halstack-react"; +import { ReactNode, SVGProps, useMemo, useState } from "react"; +import componentsList from "../common/componentsList.json"; +import { componentsRegistry, examplesRegistry } from "screens/theme-generator/componentsRegistry"; +import styled from "@emotion/styled"; +import { ComponentItem, Logos } from "./types"; + +// TODO: Both of these types should be exported by @dxc-technology/halstack-react when they are available +type SVG = ReactNode & SVGProps; + +type ListOptionType = { + /** + * 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 + * is the chosen one, take into account that the component's + * color styling tokens will not be applied to the image. + */ + icon?: string | SVG; + /** + * Label of the option to be shown in the select's listbox. + */ + label: string; + /** + * Value of the option. It should be unique and + * not an empty string, which is reserved to the empty option added + * by optional prop. + */ + value: string; +}; + +const informationIcon = ( + + + +); + +const exampleOptions = [ + { + label: "Application example", + value: "/examples/application", + icon: "settings", + }, + { + label: "Dashboard example", + value: "/examples/dashboard", + icon: "dashboard", + }, + { + label: "Form example", + value: "/examples/form", + icon: "description", + }, +]; + +const componentsExceptions = [ + "/components/application-layout", + "/components/bleed", + "/components/bulleted-list", + "/components/card", + "/components/container", + "/components/dialog", + "/components/flex", + "/components/footer", + "/components/grid", + "/components/header", + "/components/heading", + "/components/image", + "/components/inset", + "/components/paragraph", + "/components/popover", + "/components/sidenav", + "/components/typography", +]; + +const mapToSelectGroups = (data: ComponentItem[]) => { + const collectOptions = (items: ComponentItem[]): ListOptionType[] => { + return items.flatMap((item) => { + const current: ListOptionType[] = + item.path && !componentsExceptions.includes(item.path) + ? [ + { + label: item.label, + value: item.path, + icon: item.icon, + }, + ] + : []; + + const nested = item.links ? collectOptions(item.links) : []; + + return [...current, ...nested]; + }); + }; + + return data.map((category) => ({ + label: category.label, + options: collectOptions(category.links ?? []), + })); +}; + +const ThemeGeneratorPreviewPage = ({ tokens, logos }: { tokens: Record; logos: Logos }) => { + const [mode, setMode] = useState<"components" | "examples">("components"); + + const [selectedComponents, setSelectedComponents] = useState([]); + const [selectedExample, setSelectedExample] = useState(""); + + const componentOptions = useMemo(() => { + return mapToSelectGroups(componentsList as ComponentItem[]); + }, []); + + const getLabelFromValue = (value: string) => + componentOptions.flatMap((group) => group.options).find((opt) => opt.value === value)?.label; + + const displayedPreview = useMemo(() => { + if (mode === "components") { + return selectedComponents.map((component) => { + const ComponentPreview = componentsRegistry[component as keyof typeof componentsRegistry]; + return ComponentPreview ? ( + + + {getLabelFromValue(component)} + + + + ) : null; + }); + } + + if (mode === "examples") { + const ExamplePreview = examplesRegistry[selectedExample as keyof typeof examplesRegistry]; + return ExamplePreview ? : null; + } + + return null; + }, [mode, selectedComponents, selectedExample]); + + const processedLogos = useMemo(() => { + return { + mainLogo: logos.mainLogo?.[0]?.preview, + footerLogo: logos.footerLogo?.[0]?.preview, + footerReducedLogo: logos.footerReducedLogo?.[0]?.preview, + favicon: logos.favicon?.[0]?.preview, + }; + }, [logos]); + + return ( + + + + setMode(value === 1 ? "components" : "examples")} + /> + {mode === "components" && ( + { + setSelectedComponents(value); + }} + enableSelectAll + searchable + size="small" + /> + )} + + {mode === "examples" && ( + { + setSelectedExample(value); + }} + searchable + /> + )} + + {mode === "examples" && ( + + {informationIcon} + + Some components are presentational examples. The layouts shown are for demonstration purposes only and do + not represent actual components. + + + )} + {/* TODO: Turn this into a separate componente called PreviewArea or similar? */} + + {(mode === "components" && selectedComponents.length > 0) || (mode === "examples" && !!selectedExample) ? ( + + + { + if (mode === "components") { + setSelectedComponents([]); + } else { + setSelectedExample(""); + } + }} + mode="secondary" + semantic="error" + disabled={mode === "components" ? selectedComponents.length === 0 : !selectedExample} + /> + + + + + {displayedPreview} + + + + + ) : ( + + + Select {mode === "components" ? "a component" : "an example"} to preview + + + )} + + + + ); +}; + +const PreviewAreaContainer = styled.div` + flex: 1 1 0; + overflow: auto; +`; + +export default ThemeGeneratorPreviewPage; diff --git a/apps/website/screens/theme-generator/ThemeGeneratorUserGuidePage.tsx b/apps/website/screens/theme-generator/ThemeGeneratorUserGuidePage.tsx new file mode 100644 index 0000000000..ef264be7e0 --- /dev/null +++ b/apps/website/screens/theme-generator/ThemeGeneratorUserGuidePage.tsx @@ -0,0 +1,146 @@ +import Figure from "@/common/Figure"; +import Image from "@/common/Image"; +import DxcQuickNavContainer from "@/common/QuickNavContainer"; +import { DxcContainer, DxcFlex, DxcParagraph } from "@dxc-technology/halstack-react"; +import step1 from "./images/Step_1.png"; +import step2Components from "./images/Step_2_components.png"; +import step2Layout from "./images/Step_2_layout.png"; +import step3 from "./images/Step_3.png"; + +const sections = [ + { + title: "Theme Generator User Guide", + content: ( + + Building a custom theme is a simple three-step process. You can navigate between these steps at any time using + the wizard at the top of the page or the navigation buttons at the bottom. + + ), + subSections: [ + { + title: "Step 1: Define your colors", + content: Start by setting the foundation of your brand., + subSections: [ + { + title: "Core colors and semantic colors", + content: ( + + You can select the desired values using the color picker or entering the specific{" "} + hex values for your core colors ( + Primary, Secondary, Tertiary, and Neutral) along with your semantic colors ( + Info, Success, Warning, and Error). These values will be used to generate the list of + tokens that can be seen applied in the next step. These will be the base colors used to + generate the rest of the tokens, so you can get a good idea of how your theme will look by just setting + these few values. You can always go back and tweak them if you want to see how a different shade of a + specific color looks in the preview step. + + ), + }, + { + title: "Branding details", + content: ( + <> + + Brand logos can be uploaded to see how they appear within our{" "} + application layout components and a favicon can also be uploaded. The{" "} + main logo will be assigned to the Header (or the Sidenav if the Header is not + available). The footer logo is divided into two (default and reduced footer) one for + each mode of the footer, and the final slot is reserved for the favicon. + + + Note: Since we do not host these images, they are{" "} + for visualization purposes only. They help to see the theme in context, but they will + be left as empty strings in the exported theme file to be replaced with the correct asset paths. + +
+ Theme generator step 1 +
+ + ), + }, + ], + }, + { + title: "Step 2: Preview your theme", + content: ( + <> + + Once colors are set, you can move to the next step to see your theme in action. By applying the newly + generated tokens to real components and layouts, you will get a clear sense of the look + and feel of the chosen colors and logos in a live environment. + + + Remember that at any point of the process if a color doesn't look quite right in a specific layout, you + can jump back to the previous step at any time to tweak your core or semantic color values. + + + ), + subSections: [ + { + title: "Component preview mode", + content: ( + <> + + In this mode, you can add individual components to the preview area to see how your + specific tokens—such as primary button colors or semantic alerts—behave in isolation. Use the + selection menu to pick the specific elements you want to inspect. + +
+ Theme generator step 2 components +
+ + ), + }, + { + title: "Layout preview mode", + content: ( + <> + + This mode allows you to see how your theme looks when applied to different{" "} + layout options. You can see how the components look in different contexts and get a + better sense of the overall feel of your theme. You can switch between the available layouts to see + how your theme looks in each of them. + +
+ Theme generator step 2 layout +
+ + ), + }, + ], + }, + { + title: "Step 3: Review and export", + content: ( + <> + + In the third and last step, you can perform a final review of your configuration. + + + This step displays a full list of the generated tokens so you can take a final look and + review them. They can be copied directly to the clipboard or exported as + a file. If you need to make a change after you've exported, you can still go back and keep tweaking the + configurations. + +
+ Theme generator step 3 +
+ + ), + }, + ], + }, +]; +const ThemeGeneratorUserGuidePage = () => { + return ( + + + + + + + + ); +}; + +export default ThemeGeneratorUserGuidePage; diff --git a/apps/website/screens/theme-generator/components/BottomButtons.tsx b/apps/website/screens/theme-generator/components/BottomButtons.tsx new file mode 100644 index 0000000000..7a2974d19b --- /dev/null +++ b/apps/website/screens/theme-generator/components/BottomButtons.tsx @@ -0,0 +1,40 @@ +import { DxcButton, DxcContainer, DxcFlex } from "@dxc-technology/halstack-react"; +import { Step } from "../types"; + +const MIN_STEP: Step = 0; +const MAX_STEP: Step = 2; + +const BottomButtons = ({ + currentStep, + onChangeStep, + onExport, +}: { + currentStep: Step; + onChangeStep: (step: Step) => void; + onExport: () => void; +}) => ( + + + onChangeStep((currentStep - 1) as Step)} + disabled={currentStep === MIN_STEP} + size={{ height: "medium" }} + /> + {currentStep === MAX_STEP ? ( + + ) : ( + onChangeStep((currentStep + 1) as Step)} size={{ height: "medium" }} /> + )} + + +); + +export default BottomButtons; diff --git a/apps/website/screens/theme-generator/components/LandingCards.tsx b/apps/website/screens/theme-generator/components/LandingCards.tsx new file mode 100644 index 0000000000..817daaf6ae --- /dev/null +++ b/apps/website/screens/theme-generator/components/LandingCards.tsx @@ -0,0 +1,27 @@ +import { DxcContainer, DxcFlex, DxcTypography, DxcAvatar } from "@dxc-technology/halstack-react"; + +const LandingCard = ({ icon, title, description }: { icon: string; title: string; description: string }) => { + return ( + + + + + {title} + {description} + + + + ); +}; + +const LandingCards = ({ cards }: { cards: { icon: string; title: string; description: string }[] }) => { + return ( + + {cards.map((card, index) => ( + + ))} + + ); +}; + +export default LandingCards; diff --git a/apps/website/screens/theme-generator/components/LandingSteps.tsx b/apps/website/screens/theme-generator/components/LandingSteps.tsx new file mode 100644 index 0000000000..3e2456c792 --- /dev/null +++ b/apps/website/screens/theme-generator/components/LandingSteps.tsx @@ -0,0 +1,40 @@ +import { DxcContainer, DxcFlex, DxcTypography, DxcAvatar, DxcDivider, DxcInset } from "@dxc-technology/halstack-react"; +import React from "react"; + +const LandingStep = ({ index, title, description }: { index: number; title: string; description: string }) => { + return ( + + + + + {title} + + {description} + + + + + ); +}; + +const LandingSteps = ({ steps }: { steps: { title: string; description: string }[] }) => { + return ( + + + {steps.map((step, index) => ( + + + {index !== steps.length - 1 && ( + + + + + + )} + + ))} + + + ); +}; +export default LandingSteps; diff --git a/apps/website/screens/theme-generator/components/StepHeading.tsx b/apps/website/screens/theme-generator/components/StepHeading.tsx new file mode 100644 index 0000000000..e99a3d7993 --- /dev/null +++ b/apps/website/screens/theme-generator/components/StepHeading.tsx @@ -0,0 +1,14 @@ +import { DxcFlex, DxcHeading, DxcContainer, DxcTypography } from "@dxc-technology/halstack-react"; + +const StepHeading = ({ title, subtitle }: { title: string; subtitle: string }) => ( + + + + + {subtitle} + + + +); + +export default StepHeading; diff --git a/apps/website/screens/theme-generator/components/branding/BrandingColorGrid.tsx b/apps/website/screens/theme-generator/components/branding/BrandingColorGrid.tsx new file mode 100644 index 0000000000..8e907603e1 --- /dev/null +++ b/apps/website/screens/theme-generator/components/branding/BrandingColorGrid.tsx @@ -0,0 +1,40 @@ +import { DxcFlex, DxcGrid, DxcTypography } from "@dxc-technology/halstack-react"; +import { ColorCard } from "./ColorCard"; +import { Colors } from "../../types"; +import { BrandingColorGridProps } from "./types"; + +const BrandingColorGrid = ({ section, colors, onColorChange }: BrandingColorGridProps) => ( + + + + {section.icon} + + + {section.title} + + + + {section.fields.map(({ id, label, helperText }) => ( + + ))} + + +); + +export default BrandingColorGrid; diff --git a/apps/website/screens/theme-generator/components/branding/BrandingLogoGrid.tsx b/apps/website/screens/theme-generator/components/branding/BrandingLogoGrid.tsx new file mode 100644 index 0000000000..fdc70c5e1a --- /dev/null +++ b/apps/website/screens/theme-generator/components/branding/BrandingLogoGrid.tsx @@ -0,0 +1,45 @@ +import { DxcFileInput, DxcFlex, DxcGrid, DxcTypography } from "@dxc-technology/halstack-react"; +import { Logos } from "../../types"; +import { BrandingLogoGridProps } from "./types"; + +const BrandingLogoGrid = ({ section, logos, onLogoChange }: BrandingLogoGridProps) => ( + + + + {section.icon} + + + {section.title} + + + + {section.fields.map(({ id, label, helperText }) => ( + onLogoChange(id, files)} + value={logos[id as keyof Logos]} + /> + ))} + + +); + +export default BrandingLogoGrid; diff --git a/apps/website/screens/theme-generator/components/branding/ColorCard.tsx b/apps/website/screens/theme-generator/components/branding/ColorCard.tsx new file mode 100644 index 0000000000..c056ddcbbc --- /dev/null +++ b/apps/website/screens/theme-generator/components/branding/ColorCard.tsx @@ -0,0 +1,116 @@ +import { useState } from "react"; +import { DxcContainer, DxcFlex, DxcPopover, DxcTextInput } from "@dxc-technology/halstack-react"; +import styled from "@emotion/styled"; +import { SketchPicker } from "react-color"; +import useCopyToClipboard from "hooks/useCopyToClipboard"; + +const ColorBox = styled.button<{ color: string }>` + aspect-ratio: 1; + height: 72px; + border-radius: var(--border-radius-m); + background-color: ${(props) => props.color}; + cursor: pointer; + border: none; + padding: var(--spacing-padding-none); + + &:focus-visible, + &:focus { + outline-style: solid; + outline-width: var(--border-width-m); + outline-color: var(--border-color-secondary-medium); + outline-offset: 2px; + } +`; + +export const ColorCard = ({ + label, + helperText, + color, + onChange, +}: { + label: string; + helperText: string; + color: string; + onChange: (color: string) => void; +}) => { + const [isOpen, setIsOpen] = useState(false); + const [inputValue, setInputValue] = useState(color); + const [error, setError] = useState(); + + const handleBlur = ({ value, error }: { value: string; error?: string }) => { + setError(error); + if (!error) { + onChange(value); + } + }; + + const handleCopy = useCopyToClipboard(); + + return ( + + + setIsOpen(true)} + onClose={() => setIsOpen(false)} + popoverContent={ + { + setInputValue(newColor.hex); + onChange(newColor.hex); + }} + /> + } + hasTip + side="bottom" + asChild + > + setIsOpen((prev) => !prev)} + color={color} + tabIndex={0} + aria-label={`Open color picker for ${label}`} + aria-expanded={isOpen} + aria-haspopup="dialog" + /> + + + setInputValue(value)} + size="fillParent" + pattern="^#[0-9A-Fa-f]{3}$|^#[0-9A-Fa-f]{6}$" + error={error} + onBlur={handleBlur} + action={{ + icon: "Content_Copy", + onClick: () => handleCopy(inputValue), + title: "Copy the hex value", + }} + /> + + + + ); +}; diff --git a/apps/website/screens/theme-generator/components/branding/types.ts b/apps/website/screens/theme-generator/components/branding/types.ts new file mode 100644 index 0000000000..d0473835ba --- /dev/null +++ b/apps/website/screens/theme-generator/components/branding/types.ts @@ -0,0 +1,24 @@ +import { ReactNode } from "react"; +import { Colors, Field, FileData, Logos } from "../../types"; + +export type BrandingColorGridProps = { + section: { + id: string; + title: string; + icon: ReactNode; + fields: Field[]; + }; + colors: Colors; + onColorChange: (colorType: string) => (newColor: string) => void; +}; + +export type BrandingLogoGridProps = { + section: { + id: string; + title: string; + icon: ReactNode; + fields: Field[]; + }; + logos: Logos; + onLogoChange: (logoType: string, files: FileData[]) => void; +}; diff --git a/apps/website/screens/theme-generator/components/review/ReviewBrandingAssets.tsx b/apps/website/screens/theme-generator/components/review/ReviewBrandingAssets.tsx new file mode 100644 index 0000000000..833da5c061 --- /dev/null +++ b/apps/website/screens/theme-generator/components/review/ReviewBrandingAssets.tsx @@ -0,0 +1,53 @@ +import { DxcContainer, DxcFlex, DxcGrid, DxcImage, DxcParagraph, DxcTypography } from "@dxc-technology/halstack-react"; +import { useMemo } from "react"; +import { Logos } from "../../types"; + +const BrandingAsset = ({ label, logo }: { label: string; logo?: string }) => { + return ( + + + {label} + + + {logo ? ( + + ) : ( + No asset selected. + )} + + + + + ); +}; + +const ReviewBrandingAssets = ({ logos }: { logos: Logos }) => { + const brandingAssets = useMemo(() => { + return [ + { label: "Main logo", logo: logos.mainLogo?.[0]?.preview }, + { label: "Footer logo", logo: logos.footerLogo?.[0]?.preview }, + { label: "Reduced footer logo", logo: logos.footerReducedLogo?.[0]?.preview }, + { label: "Favicon", logo: logos.favicon?.[0]?.preview }, + ]; + }, [logos]); + + return ( + + {brandingAssets.some((asset) => asset.logo) ? ( + brandingAssets.map((asset) => ) + ) : ( + No branding assets selected. + )} + + ); +}; + +export default ReviewBrandingAssets; diff --git a/apps/website/screens/theme-generator/components/review/ReviewSectionContainer.tsx b/apps/website/screens/theme-generator/components/review/ReviewSectionContainer.tsx new file mode 100644 index 0000000000..a15502c24b --- /dev/null +++ b/apps/website/screens/theme-generator/components/review/ReviewSectionContainer.tsx @@ -0,0 +1,22 @@ +import { DxcContainer, DxcFlex } from "@dxc-technology/halstack-react"; + +const ReviewSectionContainer = ({ title, children }: { title: React.ReactNode; children: React.ReactNode }) => { + return ( + + + {title} + {children} + + + ); +}; + +export default ReviewSectionContainer; diff --git a/apps/website/screens/theme-generator/components/review/ReviewTokensGrid.tsx b/apps/website/screens/theme-generator/components/review/ReviewTokensGrid.tsx new file mode 100644 index 0000000000..8bead7e188 --- /dev/null +++ b/apps/website/screens/theme-generator/components/review/ReviewTokensGrid.tsx @@ -0,0 +1,60 @@ +import { DxcFlex, DxcGrid, DxcTypography } from "@dxc-technology/halstack-react"; +import { Tokens } from "../../types"; +import React, { useMemo } from "react"; +import { divideColorTokens, SHADE_VALUES } from "../../utils"; + +const ReviewTokensGrid = ({ tokens }: { tokens: Tokens }) => { + const tokenGroups = useMemo(() => divideColorTokens(tokens), [tokens]); + return ( + + {SHADE_VALUES.map((value, index) => + index === 0 ? ( + + + {value} + + + ) : ( + + {value} + + ) + )} + {Object.entries(tokenGroups).map(([group, colors]) => ( + + + + {group.charAt(0).toUpperCase() + group.slice(1)} + + + {colors.map((color: string, index: number) => ( +
+ ))} + + ))} + + ); +}; + +export default ReviewTokensGrid; diff --git a/apps/website/screens/theme-generator/components/review/ReviewTokensList.tsx b/apps/website/screens/theme-generator/components/review/ReviewTokensList.tsx new file mode 100644 index 0000000000..59a414aea1 --- /dev/null +++ b/apps/website/screens/theme-generator/components/review/ReviewTokensList.tsx @@ -0,0 +1,13 @@ +import { DxcContainer, DxcTypography } from "@dxc-technology/halstack-react"; + +const ReviewTokensList = ({ themeJson }: { themeJson: string }) => { + return ( + + + {themeJson} + + + ); +}; + +export default ReviewTokensList; diff --git a/apps/website/screens/theme-generator/componentsRegistry.tsx b/apps/website/screens/theme-generator/componentsRegistry.tsx new file mode 100644 index 0000000000..5161343014 --- /dev/null +++ b/apps/website/screens/theme-generator/componentsRegistry.tsx @@ -0,0 +1,84 @@ +import { + AccordionPreview, + AlertPreview, + AvatarPreview, + BadgePreview, + BreadcrumbsPreview, + ButtonPreview, + CheckboxPreview, + ChipPreview, + ContextualMenuPreview, + DataGridPreview, + DateInputPreview, + DividerPreview, + DropdownPreview, + FileInputPreview, + LinkPreview, + NavTabsPreview, + NumberInputPreview, + PaginatorPreview, + PasswordInputPreview, + ProgressBarPreview, + QuickNavPreview, + RadioGroupPreview, + ResultsetTablePreview, + SelectPreview, + SliderPreview, + SpinnerPreview, + StatusLightPreview, + SwitchPreview, + TablePreview, + TabsPreview, + TextareaPreview, + TextInputPreview, + ToastPreview, + ToggleGroupPreview, + TooltipPreview, + WizardPreview, +} from "./previews/components"; +import { ApplicationPreview, DashboardPreview, FormPreview } from "./previews/examples"; + +export const componentsRegistry = { + "/components/accordion": AccordionPreview, + "/components/avatar": AvatarPreview, + "/components/divider": DividerPreview, + "/components/wizard": WizardPreview, + "/components/data-grid": DataGridPreview, + "/components/paginator": PaginatorPreview, + "/components/resultset-table": ResultsetTablePreview, + "/components/table": TablePreview, + "/components/alert": AlertPreview, + "/components/progress-bar": ProgressBarPreview, + "/components/spinner": SpinnerPreview, + "/components/toast": ToastPreview, + "/components/tooltip": TooltipPreview, + "/components/button": ButtonPreview, + "/components/checkbox": CheckboxPreview, + "/components/date-input": DateInputPreview, + "/components/file-input": FileInputPreview, + "/components/number-input": NumberInputPreview, + "/components/password-input": PasswordInputPreview, + "/components/radio-group": RadioGroupPreview, + "/components/select": SelectPreview, + "/components/slider": SliderPreview, + "/components/switch": SwitchPreview, + "/components/text-input": TextInputPreview, + "/components/textarea": TextareaPreview, + "/components/toggle-group": ToggleGroupPreview, + "/components/breadcrumbs": BreadcrumbsPreview, + "/components/contextual-menu": ContextualMenuPreview, + "/components/dropdown": DropdownPreview, + "/components/link": LinkPreview, + "/components/nav-tabs": NavTabsPreview, + "/components/quick-nav": QuickNavPreview, + "/components/tabs": TabsPreview, + "/components/badge": BadgePreview, + "/components/chip": ChipPreview, + "/components/status-light": StatusLightPreview, +}; + +export const examplesRegistry = { + "/examples/application": ApplicationPreview, + "/examples/dashboard": DashboardPreview, + "/examples/form": FormPreview, +}; diff --git a/apps/website/screens/theme-generator/images/Step_1.png b/apps/website/screens/theme-generator/images/Step_1.png new file mode 100644 index 0000000000..201b8ae905 Binary files /dev/null and b/apps/website/screens/theme-generator/images/Step_1.png differ diff --git a/apps/website/screens/theme-generator/images/Step_2_components.png b/apps/website/screens/theme-generator/images/Step_2_components.png new file mode 100644 index 0000000000..d1fe5b6d38 Binary files /dev/null and b/apps/website/screens/theme-generator/images/Step_2_components.png differ diff --git a/apps/website/screens/theme-generator/images/Step_2_layout.png b/apps/website/screens/theme-generator/images/Step_2_layout.png new file mode 100644 index 0000000000..3da4f5c47f Binary files /dev/null and b/apps/website/screens/theme-generator/images/Step_2_layout.png differ diff --git a/apps/website/screens/theme-generator/images/Step_3.png b/apps/website/screens/theme-generator/images/Step_3.png new file mode 100644 index 0000000000..8f8f316372 Binary files /dev/null and b/apps/website/screens/theme-generator/images/Step_3.png differ diff --git a/apps/website/screens/theme-generator/previews/components/AccordionPreview.tsx b/apps/website/screens/theme-generator/previews/components/AccordionPreview.tsx new file mode 100644 index 0000000000..a3d73981ce --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/AccordionPreview.tsx @@ -0,0 +1,22 @@ +import { DxcAccordion, DxcInset, DxcParagraph } from "@dxc-technology/halstack-react"; + +const AccordionPreview = () => { + return ( + + + + + This section contains information related to the user's account such as username, email, and preferences. + + + + + ); +}; + +export default AccordionPreview; diff --git a/apps/website/screens/theme-generator/previews/components/AlertPreview.tsx b/apps/website/screens/theme-generator/previews/components/AlertPreview.tsx new file mode 100644 index 0000000000..8d35c1f924 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/AlertPreview.tsx @@ -0,0 +1,41 @@ +import { DxcAlert, DxcFlex } from "@dxc-technology/halstack-react"; + +const AlertPreview = () => { + return ( + + {} }} + secondaryAction={{ label: "Don't show", onClick: () => {} }} + semantic="success" + title="Update completed" + /> + + {} }} + secondaryAction={{ label: "Don't show", onClick: () => {} }} + semantic="info" + title="System information" + /> + + {} }} + secondaryAction={{ label: "Don't show", onClick: () => {} }} + semantic="warning" + title="Password expiration warning" + /> + + {} }} + secondaryAction={{ label: "Don't show", onClick: () => {} }} + semantic="error" + title="Request failed" + /> + + ); +}; + +export default AlertPreview; diff --git a/apps/website/screens/theme-generator/previews/components/AvatarPreview.tsx b/apps/website/screens/theme-generator/previews/components/AvatarPreview.tsx new file mode 100644 index 0000000000..c7e9364709 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/AvatarPreview.tsx @@ -0,0 +1,62 @@ +import { DxcAvatar, DxcFlex } from "@dxc-technology/halstack-react"; + +const AvatarPreview = () => { + return ( + + + + + + + + + + + + + + + ); +}; + +export default AvatarPreview; diff --git a/apps/website/screens/theme-generator/previews/components/BadgePreview.tsx b/apps/website/screens/theme-generator/previews/components/BadgePreview.tsx new file mode 100644 index 0000000000..b95f70c37a --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/BadgePreview.tsx @@ -0,0 +1,19 @@ +import { DxcBadge, DxcFlex } from "@dxc-technology/halstack-react"; + +const BadgePreview = () => { + return ( + + + + + + + + + + + + ); +}; + +export default BadgePreview; diff --git a/apps/website/screens/theme-generator/previews/components/BreadcrumbsPreview.tsx b/apps/website/screens/theme-generator/previews/components/BreadcrumbsPreview.tsx new file mode 100644 index 0000000000..fc79a27653 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/BreadcrumbsPreview.tsx @@ -0,0 +1,7 @@ +import { DxcBreadcrumbs } from "@dxc-technology/halstack-react"; + +const BreadcrumbsPreview = () => { + return ; +}; + +export default BreadcrumbsPreview; diff --git a/apps/website/screens/theme-generator/previews/components/ButtonPreview.tsx b/apps/website/screens/theme-generator/previews/components/ButtonPreview.tsx new file mode 100644 index 0000000000..b6e0531105 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/ButtonPreview.tsx @@ -0,0 +1,14 @@ +import { DxcButton, DxcFlex } from "@dxc-technology/halstack-react"; + +const ButtonPreview = () => { + return ( + + + + + + + ); +}; + +export default ButtonPreview; diff --git a/apps/website/screens/theme-generator/previews/components/CheckboxPreview.tsx b/apps/website/screens/theme-generator/previews/components/CheckboxPreview.tsx new file mode 100644 index 0000000000..a378aed305 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/CheckboxPreview.tsx @@ -0,0 +1,13 @@ +import { DxcCheckbox, DxcFlex } from "@dxc-technology/halstack-react"; + +const CheckboxPreview = () => { + return ( + + + + + + ); +}; + +export default CheckboxPreview; diff --git a/apps/website/screens/theme-generator/previews/components/ChipPreview.tsx b/apps/website/screens/theme-generator/previews/components/ChipPreview.tsx new file mode 100644 index 0000000000..e369773615 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/ChipPreview.tsx @@ -0,0 +1,14 @@ +import { DxcChip, DxcFlex } from "@dxc-technology/halstack-react"; + +// TODO: It gets mixed with the background color +const ChipPreview = () => { + return ( + + + + + + ); +}; + +export default ChipPreview; diff --git a/apps/website/screens/theme-generator/previews/components/ContextualMenuPreview.tsx b/apps/website/screens/theme-generator/previews/components/ContextualMenuPreview.tsx new file mode 100644 index 0000000000..6766b1ef5f --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/ContextualMenuPreview.tsx @@ -0,0 +1,50 @@ +import { DxcContextualMenu, DxcBadge, DxcContainer } from "@dxc-technology/halstack-react"; + +const contextualMenuItems = [ + { + title: "File", + items: [ + { + label: "New", + icon: "note_add", + items: [ + { label: "Project" }, + { + label: "Template", + items: [ + { + label: "Web Template", + icon: "web", + badge: , + }, + { label: "Mobile Template", selectedByDefault: true }, + ], + }, + ], + badge: , + }, + { label: "Open", icon: "folder_open" }, + ], + }, + { + title: "Edit", + items: [ + { label: "Undo" }, + { + label: "Preferences", + items: [{ label: "Theme" }, { label: "Notifications" }], + }, + { label: "Redo" }, + ], + }, +]; + +const ContextualMenuPreview = () => { + return ( + + + + ); +}; + +export default ContextualMenuPreview; diff --git a/apps/website/screens/theme-generator/previews/components/DataGridPreview.tsx b/apps/website/screens/theme-generator/previews/components/DataGridPreview.tsx new file mode 100644 index 0000000000..a56008bbcd --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/DataGridPreview.tsx @@ -0,0 +1,159 @@ +import React, { useState } from "react"; +import { DxcDataGrid, DxcContainer } from "@dxc-technology/halstack-react"; +import type { GridColumn } from "../../../../../../packages/lib/src/data-grid/types"; + +const actions = [ + { + icon: "filled_edit", + title: "icon", + onClick: () => {}, + }, + { + icon: "filled_delete", + title: "icon", + onClick: () => {}, + disabled: true, + }, +]; + +const columns: GridColumn[] = [ + { + key: "id", + label: "ID", + resizable: true, + sortable: true, + draggable: false, + alignment: "left", + }, + { + key: "task", + label: "Title", + resizable: true, + sortable: true, + draggable: true, + textEditable: true, + alignment: "left", + }, + { + key: "complete", + label: " % Complete", + resizable: true, + sortable: true, + draggable: true, + alignment: "right", + summaryKey: "label", + }, + { + key: "priority", + label: "Priority", + resizable: true, + draggable: true, + alignment: "center", + summaryKey: "total", + }, + { + key: "actions", + label: "Actions", + alignment: "center", + }, +]; +const expandableRows = [ + { + id: 1, + task: "Task 1", + complete: 46, + priority: "High", + issueType: "Bug", + expandedContent: Custom content 1, + actions: , + }, + { + id: 2, + task: "Task 2", + complete: 51, + priority: "High", + issueType: "Epic", + expandedContent: Custom content 2, + actions: , + }, + { + id: 3, + task: "Task 3", + complete: 40, + priority: "High", + issueType: "Improvement", + expandedContent: Custom content 3, + actions: , + }, + { + id: 4, + task: "Task 4", + complete: 10, + priority: "High", + issueType: "Improvement", + expandedContent: Custom content 4, + actions: , + }, + { + id: 5, + task: "Task 5", + complete: 68, + priority: "High", + issueType: "Improvement", + expandedContent: Custom content 5, + actions: , + }, + { + id: 6, + task: "Task 6", + complete: 37, + priority: "High", + issueType: "Improvement", + expandedContent: Custom content 6, + actions: , + }, + { + id: 7, + task: "Task 7", + complete: 73, + priority: "Medium", + issueType: "Story", + expandedContent: Custom content 7, + actions: , + }, + { + id: 8, + task: "Task 8", + complete: 27, + priority: "Medium", + issueType: "Story", + expandedContent: Custom content 8, + actions: , + }, + { + id: 9, + task: "Task 9", + complete: 36, + priority: "Critical", + issueType: "Epic", + expandedContent: Custom content 9, + actions: , + }, +]; + +const DatagridPreview = () => { + const [selectedRows, setSelectedRows] = useState((): Set => new Set()); + + return ( + + ); +}; + +export default DatagridPreview; diff --git a/apps/website/screens/theme-generator/previews/components/DateInputPreview.tsx b/apps/website/screens/theme-generator/previews/components/DateInputPreview.tsx new file mode 100644 index 0000000000..223c22d0b4 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/DateInputPreview.tsx @@ -0,0 +1,34 @@ +import { DxcDateInput, DxcFlex } from "@dxc-technology/halstack-react"; + +const DateInputPreview = () => { + return ( + + + + + + ); +}; + +export default DateInputPreview; diff --git a/apps/website/screens/theme-generator/previews/components/DividerPreview.tsx b/apps/website/screens/theme-generator/previews/components/DividerPreview.tsx new file mode 100644 index 0000000000..3a4970b2b9 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/DividerPreview.tsx @@ -0,0 +1,13 @@ +import { DxcDivider, DxcFlex, DxcTypography } from "@dxc-technology/halstack-react"; + +const DividerPreview = () => { + return ( + + Content above + + Content below + + ); +}; + +export default DividerPreview; diff --git a/apps/website/screens/theme-generator/previews/components/DropdownPreview.tsx b/apps/website/screens/theme-generator/previews/components/DropdownPreview.tsx new file mode 100644 index 0000000000..8adc22cf23 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/DropdownPreview.tsx @@ -0,0 +1,25 @@ +import { DxcDropdown } from "@dxc-technology/halstack-react"; + +const DropdownPreview = () => { + const iconOptions = [ + { + value: "1", + label: "Android", + icon: "filled_phone_android", + }, + { + value: "2", + label: "Windows", + icon: "desktop_windows", + }, + { + value: "3", + label: "IOS", + icon: "filled_phone_iphone", + }, + ]; + + return {}} icon="download" label="Device" />; +}; + +export default DropdownPreview; diff --git a/apps/website/screens/theme-generator/previews/components/FileInputPreview.tsx b/apps/website/screens/theme-generator/previews/components/FileInputPreview.tsx new file mode 100644 index 0000000000..950b55f6ec --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/FileInputPreview.tsx @@ -0,0 +1,26 @@ +import { DxcFileInput, DxcFlex } from "@dxc-technology/halstack-react"; + +const FileInputPreview = () => { + const file = new File(["file1"], "file.pdf", { type: "text/plain" }); + + const fileExample = [ + { + file: file, + }, + ]; + + const fileExampleError = [ + { + error: "Error message", + file: file, + }, + ]; + return ( + + {}} value={fileExample} /> + {}} value={fileExampleError} /> + + ); +}; + +export default FileInputPreview; diff --git a/apps/website/screens/theme-generator/previews/components/LinkPreview.tsx b/apps/website/screens/theme-generator/previews/components/LinkPreview.tsx new file mode 100644 index 0000000000..156d937a62 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/LinkPreview.tsx @@ -0,0 +1,11 @@ +import { DxcLink } from "@dxc-technology/halstack-react"; + +const LinkPreview = () => { + return ( + + View Documentation + + ); +}; + +export default LinkPreview; diff --git a/apps/website/screens/theme-generator/previews/components/NavTabsPreview.tsx b/apps/website/screens/theme-generator/previews/components/NavTabsPreview.tsx new file mode 100644 index 0000000000..750e2db9d5 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/NavTabsPreview.tsx @@ -0,0 +1,25 @@ +import { DxcNavTabs } from "@dxc-technology/halstack-react"; + +const TabsPreview = () => { + return ( + + {}}> + Dashboard + + + {}}> + Messages + + + {}}> + Notifications + + + {}}> + Settings + + + ); +}; + +export default TabsPreview; diff --git a/apps/website/screens/theme-generator/previews/components/NumberInputPreview.tsx b/apps/website/screens/theme-generator/previews/components/NumberInputPreview.tsx new file mode 100644 index 0000000000..560a5e34cf --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/NumberInputPreview.tsx @@ -0,0 +1,21 @@ +import { DxcFlex, DxcNumberInput } from "@dxc-technology/halstack-react"; + +const NumberInputPreview = () => { + return ( + + + + + ); +}; + +export default NumberInputPreview; diff --git a/apps/website/screens/theme-generator/previews/components/PaginatorPreview.tsx b/apps/website/screens/theme-generator/previews/components/PaginatorPreview.tsx new file mode 100644 index 0000000000..8604e1c5b1 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/PaginatorPreview.tsx @@ -0,0 +1,16 @@ +import { DxcPaginator } from "@dxc-technology/halstack-react"; + +const PaginatorPreview = () => { + return ( + {}} + itemsPerPageOptions={[5, 10, 15]} + showGoToPage + /> + ); +}; + +export default PaginatorPreview; diff --git a/apps/website/screens/theme-generator/previews/components/PasswordInputPreview.tsx b/apps/website/screens/theme-generator/previews/components/PasswordInputPreview.tsx new file mode 100644 index 0000000000..89ac28bd59 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/PasswordInputPreview.tsx @@ -0,0 +1,16 @@ +import { DxcFlex, DxcPasswordInput } from "@dxc-technology/halstack-react"; + +const PasswordInputPreview = () => { + return ( + + + + + ); +}; + +export default PasswordInputPreview; diff --git a/apps/website/screens/theme-generator/previews/components/ProgressBarPreview.tsx b/apps/website/screens/theme-generator/previews/components/ProgressBarPreview.tsx new file mode 100644 index 0000000000..d182dd6198 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/ProgressBarPreview.tsx @@ -0,0 +1,12 @@ +import { DxcProgressBar, DxcFlex } from "@dxc-technology/halstack-react"; + +const ProgressBarPreview = () => { + return ( + + + + + ); +}; + +export default ProgressBarPreview; diff --git a/apps/website/screens/theme-generator/previews/components/QuickNavPreview.tsx b/apps/website/screens/theme-generator/previews/components/QuickNavPreview.tsx new file mode 100644 index 0000000000..cfe91754e8 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/QuickNavPreview.tsx @@ -0,0 +1,13 @@ +import { DxcQuickNav } from "@dxc-technology/halstack-react"; + +const QuickNavPreview = () => { + const links = [ + { label: "Overview", href: "#overview" }, + { label: "Features", href: "#features" }, + { label: "Pricing", href: "#pricing" }, + ]; + + return ; +}; + +export default QuickNavPreview; diff --git a/apps/website/screens/theme-generator/previews/components/RadioGroupPreview.tsx b/apps/website/screens/theme-generator/previews/components/RadioGroupPreview.tsx new file mode 100644 index 0000000000..1b96a112a9 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/RadioGroupPreview.tsx @@ -0,0 +1,22 @@ +import { DxcRadioGroup, DxcFlex } from "@dxc-technology/halstack-react"; + +const RadioGroupPreview = () => { + const options = [ + { label: "Basic Plan", value: "basic" }, + { label: "Pro Plan", value: "pro" }, + { label: "Enterprise Plan", value: "enterprise" }, + ]; + + return ( + + + + + ); +}; + +export default RadioGroupPreview; diff --git a/apps/website/screens/theme-generator/previews/components/ResultsetTablePreview.tsx b/apps/website/screens/theme-generator/previews/components/ResultsetTablePreview.tsx new file mode 100644 index 0000000000..566bf08de3 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/ResultsetTablePreview.tsx @@ -0,0 +1,54 @@ +import { DxcResultsetTable } from "@dxc-technology/halstack-react"; + +const deleteIcon = ( + + + + +); + +const actions = [ + { + icon: "filled_edit", + title: "icon", + onClick: () => {}, + }, + { + icon: deleteIcon, + title: "icon", + onClick: () => {}, + disabled: true, + }, +]; + +const ResultsetTablePreview = () => { + const columns = [ + { displayValue: "Name" }, + { displayValue: "Email" }, + { displayValue: "Role" }, + { displayValue: "Action" }, + ]; + + const rows = [ + [ + { displayValue: "John Doe" }, + { displayValue: "john@example.com" }, + { displayValue: "Developer" }, + { + displayValue: , + }, + ], + [ + { displayValue: "Jane Smith" }, + { displayValue: "jane@example.com" }, + { displayValue: "Designer" }, + { + displayValue: , + }, + ], + ]; + + return ; +}; + +export default ResultsetTablePreview; diff --git a/apps/website/screens/theme-generator/previews/components/SelectPreview.tsx b/apps/website/screens/theme-generator/previews/components/SelectPreview.tsx new file mode 100644 index 0000000000..6135107953 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/SelectPreview.tsx @@ -0,0 +1,12 @@ +import { DxcSelect } from "@dxc-technology/halstack-react"; + +const SelectPreview = () => { + const options = [ + { value: "basic", label: "Basic Plan" }, + { value: "pro", label: "Pro Plan" }, + { value: "enterprise", label: "Enterprise Plan" }, + ]; + + return ; +}; +export default SelectPreview; diff --git a/apps/website/screens/theme-generator/previews/components/SliderPreview.tsx b/apps/website/screens/theme-generator/previews/components/SliderPreview.tsx new file mode 100644 index 0000000000..e26e21037f --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/SliderPreview.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import { DxcSlider } from "@dxc-technology/halstack-react"; + +const SliderPreview = () => { + return ; +}; + +export default SliderPreview; diff --git a/apps/website/screens/theme-generator/previews/components/SpinnerPreview.tsx b/apps/website/screens/theme-generator/previews/components/SpinnerPreview.tsx new file mode 100644 index 0000000000..a8849ffd17 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/SpinnerPreview.tsx @@ -0,0 +1,12 @@ +import { DxcSpinner, DxcFlex } from "@dxc-technology/halstack-react"; + +const SpinnerPreview = () => { + return ( + + + + + ); +}; + +export default SpinnerPreview; diff --git a/apps/website/screens/theme-generator/previews/components/StatusLightPreview.tsx b/apps/website/screens/theme-generator/previews/components/StatusLightPreview.tsx new file mode 100644 index 0000000000..e029e325a7 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/StatusLightPreview.tsx @@ -0,0 +1,14 @@ +import { DxcStatusLight, DxcFlex } from "@dxc-technology/halstack-react"; + +const StatusLightPreview = () => { + return ( + + + + + + + ); +}; + +export default StatusLightPreview; diff --git a/apps/website/screens/theme-generator/previews/components/SwitchPreview.tsx b/apps/website/screens/theme-generator/previews/components/SwitchPreview.tsx new file mode 100644 index 0000000000..55c81ccebf --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/SwitchPreview.tsx @@ -0,0 +1,12 @@ +import { DxcSwitch, DxcFlex } from "@dxc-technology/halstack-react"; + +const SwitchPreview = () => { + return ( + + + + + ); +}; + +export default SwitchPreview; diff --git a/apps/website/screens/theme-generator/previews/components/TablePreview.tsx b/apps/website/screens/theme-generator/previews/components/TablePreview.tsx new file mode 100644 index 0000000000..a5b5d5d8b0 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/TablePreview.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { DxcTable } from "@dxc-technology/halstack-react"; + +const TablePreview = () => { + return ( + + + + Name + Email + Role + + + + + John Doe + john@example.com + Developer + + + Jane Smith + jane@example.com + Designer + + + + ); +}; + +export default TablePreview; diff --git a/apps/website/screens/theme-generator/previews/components/TabsPreview.tsx b/apps/website/screens/theme-generator/previews/components/TabsPreview.tsx new file mode 100644 index 0000000000..55af3a1172 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/TabsPreview.tsx @@ -0,0 +1,31 @@ +import { DxcTabs } from "@dxc-technology/halstack-react"; + +const TabsPreview = () => { + const mobileIcon = ( + + + + + + + + + + + ); + return ( + + + <> + + + <> + + + <> + + + ); +}; + +export default TabsPreview; diff --git a/apps/website/screens/theme-generator/previews/components/TextInputPreview.tsx b/apps/website/screens/theme-generator/previews/components/TextInputPreview.tsx new file mode 100644 index 0000000000..7a198db8b6 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/TextInputPreview.tsx @@ -0,0 +1,20 @@ +import { DxcFlex, DxcTextInput } from "@dxc-technology/halstack-react"; +const TextInputPreview = () => { + return ( + + + + + ); +}; + +export default TextInputPreview; diff --git a/apps/website/screens/theme-generator/previews/components/TextareaPreview.tsx b/apps/website/screens/theme-generator/previews/components/TextareaPreview.tsx new file mode 100644 index 0000000000..c2d14728b2 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/TextareaPreview.tsx @@ -0,0 +1,22 @@ +import { DxcFlex, DxcTextarea } from "@dxc-technology/halstack-react"; +const TextareaPreview = () => { + return ( + + + + + ); +}; + +export default TextareaPreview; diff --git a/apps/website/screens/theme-generator/previews/components/ToastPreview.tsx b/apps/website/screens/theme-generator/previews/components/ToastPreview.tsx new file mode 100644 index 0000000000..dd410d3d18 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/ToastPreview.tsx @@ -0,0 +1,41 @@ +import { DxcButton, DxcFlex, useToast, DxcToastsQueue } from "@dxc-technology/halstack-react"; + +const ToastButtons = () => { + const toast = useToast(); + + const showSuccessToast = () => { + toast.success({ message: "Success! Operation completed." }); + }; + + const showWarningToast = () => { + toast.warning({ message: "Warning! Please review this." }); + }; + + const showInfoToast = () => { + toast.info({ message: "Info: Here's some information." }); + }; + const showLoadingToast = () => { + toast.loading({ message: "Loading: Please wait." }); + }; + + return ( + + + + + + + ); +}; + +// Wrapper component with its own ToastsQueue +// This ensures toasts render within the themed HalstackProvider in PreviewArea +const ToastPreview = () => { + return ( + + + + ); +}; + +export default ToastPreview; diff --git a/apps/website/screens/theme-generator/previews/components/ToggleGroupPreview.tsx b/apps/website/screens/theme-generator/previews/components/ToggleGroupPreview.tsx new file mode 100644 index 0000000000..6a2f13003e --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/ToggleGroupPreview.tsx @@ -0,0 +1,20 @@ +import { DxcToggleGroup } from "@dxc-technology/halstack-react"; + +const ToggleGroupPreview = () => { + const optionsWithIcons = [ + { + value: 1, + label: "Light Mode", + icon: "wb_sunny", + }, + { + value: 2, + label: "Dark Mode", + icon: "nights_stay", + }, + ]; + + return ; +}; + +export default ToggleGroupPreview; diff --git a/apps/website/screens/theme-generator/previews/components/TooltipPreview.tsx b/apps/website/screens/theme-generator/previews/components/TooltipPreview.tsx new file mode 100644 index 0000000000..a654d446bb --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/TooltipPreview.tsx @@ -0,0 +1,11 @@ +import { DxcButton, DxcTooltip } from "@dxc-technology/halstack-react"; + +const TooltipPreview = () => { + return ( + + + + ); +}; + +export default TooltipPreview; diff --git a/apps/website/screens/theme-generator/previews/components/WizardPreview.tsx b/apps/website/screens/theme-generator/previews/components/WizardPreview.tsx new file mode 100644 index 0000000000..0142021932 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/WizardPreview.tsx @@ -0,0 +1,32 @@ +import { DxcWizard } from "@dxc-technology/halstack-react"; + +const WizardPreview = () => { + const stepsWithIcons = [ + { + label: "Account setup", + description: "Create your account credentials", + valid: true, + icon: "person", + }, + { + label: "Address information", + description: "Provide your home address details", + valid: true, + icon: "home", + }, + { + label: "Employment details", + description: "Add your current job information", + icon: "work", + }, + { + label: "Review and submit", + description: "Confirm all information before submission", + disabled: true, + icon: "thumb_up", + }, + ]; + return ; +}; + +export default WizardPreview; diff --git a/apps/website/screens/theme-generator/previews/components/index.ts b/apps/website/screens/theme-generator/previews/components/index.ts new file mode 100644 index 0000000000..b4aa477879 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/components/index.ts @@ -0,0 +1,36 @@ +export { default as AccordionPreview } from "./AccordionPreview"; +export { default as AlertPreview } from "./AlertPreview"; +export { default as AvatarPreview } from "./AvatarPreview"; +export { default as BadgePreview } from "./BadgePreview"; +export { default as BreadcrumbsPreview } from "./BreadcrumbsPreview"; +export { default as ButtonPreview } from "./ButtonPreview"; +export { default as CheckboxPreview } from "./CheckboxPreview"; +export { default as ChipPreview } from "./ChipPreview"; +export { default as ContextualMenuPreview } from "./ContextualMenuPreview"; +export { default as DataGridPreview } from "./DataGridPreview"; +export { default as DateInputPreview } from "./DateInputPreview"; +export { default as DividerPreview } from "./DividerPreview"; +export { default as DropdownPreview } from "./DropdownPreview"; +export { default as FileInputPreview } from "./FileInputPreview"; +export { default as LinkPreview } from "./LinkPreview"; +export { default as NavTabsPreview } from "./NavTabsPreview"; +export { default as NumberInputPreview } from "./NumberInputPreview"; +export { default as PaginatorPreview } from "./PaginatorPreview"; +export { default as PasswordInputPreview } from "./PasswordInputPreview"; +export { default as ProgressBarPreview } from "./ProgressBarPreview"; +export { default as QuickNavPreview } from "./QuickNavPreview"; +export { default as RadioGroupPreview } from "./RadioGroupPreview"; +export { default as ResultsetTablePreview } from "./ResultsetTablePreview"; +export { default as SelectPreview } from "./SelectPreview"; +export { default as SliderPreview } from "./SliderPreview"; +export { default as SpinnerPreview } from "./SpinnerPreview"; +export { default as StatusLightPreview } from "./StatusLightPreview"; +export { default as SwitchPreview } from "./SwitchPreview"; +export { default as TablePreview } from "./TablePreview"; +export { default as TabsPreview } from "./TabsPreview"; +export { default as TextareaPreview } from "./TextareaPreview"; +export { default as TextInputPreview } from "./TextInputPreview"; +export { default as ToastPreview } from "./ToastPreview"; +export { default as ToggleGroupPreview } from "./ToggleGroupPreview"; +export { default as TooltipPreview } from "./TooltipPreview"; +export { default as WizardPreview } from "./WizardPreview"; diff --git a/apps/website/screens/theme-generator/previews/examples/ApplicationPreview.tsx b/apps/website/screens/theme-generator/previews/examples/ApplicationPreview.tsx new file mode 100644 index 0000000000..4634a6a0db --- /dev/null +++ b/apps/website/screens/theme-generator/previews/examples/ApplicationPreview.tsx @@ -0,0 +1,365 @@ +import React, { useState } from "react"; +import { + DxcFlex, + DxcButton, + DxcResultsetTable, + DxcDataGrid, + DxcHeading, + DxcParagraph, + DxcDivider, + DxcApplicationLayout, + DxcAvatar, + DxcBadge, + DxcInset, +} from "@dxc-technology/halstack-react"; +import { Logos } from "screens/theme-generator/types"; +import { GridRow } from "../../../../../../packages/lib/src/data-grid/types"; + +const columnsDatagrid = [ + { + key: "policyId", + label: "Policy ID", + sortable: true, + }, + { + key: "memberName", + label: "Member Name", + sortable: true, + }, + { + key: "policyType", + label: "Policy Type", + sortable: true, + }, + { + key: "startDate", + label: "Start Date", + sortable: true, + }, + { + key: "endDate", + label: "End Date", + sortable: true, + }, + { + key: "premium", + label: "Premium", + sortable: true, + }, + { + key: "status", + label: "Status", + sortable: true, + }, +]; + +const rowsDatagrid = [ + { + policyId: "REC-001", + memberName: "Primary Record A", + policyType: "Category Alpha", + startDate: "Jan 1, 2024", + endDate: "Dec 31, 2024", + premium: "$1,000", + status: "Active", + childRows: [ + { + policyId: "REC-001-1", + memberName: "Sub Record A1", + policyType: "Subcategory A", + startDate: "Jan 1, 2024", + endDate: "Dec 31, 2024", + premium: "$400", + status: "Active", + }, + { + policyId: "REC-001-2", + memberName: "Sub Record A2", + policyType: "Subcategory A", + startDate: "Jan 1, 2024", + endDate: "Dec 31, 2024", + premium: "$600", + status: "Active", + }, + ], + }, + { + policyId: "REC-002", + memberName: "Primary Record B", + policyType: "Category Beta", + startDate: "Feb 15, 2024", + endDate: "Feb 14, 2025", + premium: "$750", + status: "Active", + childRows: [ + { + policyId: "REC-002-1", + memberName: "Sub Record B1", + policyType: "Subcategory B", + startDate: "Feb 15, 2024", + endDate: "Feb 14, 2025", + premium: "$750", + status: "Active", + }, + ], + }, + { + policyId: "REC-003", + memberName: "Primary Record C", + policyType: "Category Gamma", + startDate: "Mar 10, 2024", + endDate: "Mar 9, 2025", + premium: "$500", + status: "In Progress", + childRows: [ + { + policyId: "REC-003-1", + memberName: "Sub Record C1", + policyType: "Subcategory C", + startDate: "Mar 10, 2024", + endDate: "Mar 9, 2025", + premium: "$250", + status: "In Progress", + }, + { + policyId: "REC-003-2", + memberName: "Sub Record C2", + policyType: "Subcategory C", + startDate: "Mar 10, 2024", + endDate: "Mar 9, 2025", + premium: "$250", + status: "In Progress", + }, + ], + }, + { + policyId: "REC-004", + memberName: "Primary Record D", + policyType: "Category Delta", + startDate: "Apr 1, 2024", + endDate: "Mar 31, 2025", + premium: "$900", + status: "Pending", + childRows: [ + { + policyId: "REC-004-1", + memberName: "Sub Record D1", + policyType: "Subcategory D", + startDate: "Apr 1, 2024", + endDate: "Mar 31, 2025", + premium: "$500", + status: "Pending", + }, + { + policyId: "REC-004-2", + memberName: "Sub Record D2", + policyType: "Subcategory D", + startDate: "Apr 1, 2024", + endDate: "Mar 31, 2025", + premium: "$400", + status: "Pending", + }, + ], + }, + { + policyId: "REC-005", + memberName: "Primary Record E", + policyType: "Category Epsilon", + startDate: "May 20, 2024", + endDate: "May 19, 2025", + premium: "$300", + status: "Completed", + }, +]; + +const columns = [ + { displayValue: "Name" }, + { displayValue: "Relationship" }, + { displayValue: "Age" }, + { displayValue: "Occupation" }, + { displayValue: "Coverage Amount" }, + { displayValue: "Actions" }, +]; + +const actions = [ + { + icon: "edit", + title: "Edit Member", + onClick: () => {}, + }, + { + icon: "visibility", + title: "View Details", + onClick: () => {}, + }, +]; + +const rows = [ + [ + { displayValue: "John Doe" }, + { displayValue: "Policyholder" }, + { displayValue: "42" }, + { displayValue: "Software Engineer" }, + { displayValue: "$500,000" }, + { displayValue: }, + ], + [ + { displayValue: "Jane Doe" }, + { displayValue: "Spouse" }, + { displayValue: "40" }, + { displayValue: "Teacher" }, + { displayValue: "$300,000" }, + { displayValue: }, + ], + [ + { displayValue: "Emily Doe" }, + { displayValue: "Daughter" }, + { displayValue: "14" }, + { displayValue: "Student" }, + { displayValue: "$100,000" }, + { displayValue: }, + ], + [ + { displayValue: "Michael Doe" }, + { displayValue: "Son" }, + { displayValue: "10" }, + { displayValue: "Student" }, + { displayValue: "$100,000" }, + { displayValue: }, + ], +]; + +const ApplicationPreview = ({ logos }: { logos: Logos }) => { + const [selectedRows, setSelectedRows] = useState(new Set()); + + return ( + + } + header={ + , + }, + { label: "Claims", icon: "assignment" }, + { label: "Documents", icon: "folder" }, + { label: "Payments", icon: "payment" }, + ]} + sideContent={ + <> + + + + } + /> + } + sidenav={ + + } + > + + +
+ + + + Manage your family's insurance policies, view coverage details, and track policy status all in one + place. + + + + + + + + View and manage coverage information for all family members + + + + + + + + + + + Complete overview of all insurance policies associated with your family + + + + + + + + +
+
+
+
+ ); +}; + +export default ApplicationPreview; diff --git a/apps/website/screens/theme-generator/previews/examples/DashboardPreview.tsx b/apps/website/screens/theme-generator/previews/examples/DashboardPreview.tsx new file mode 100644 index 0000000000..04431c02b2 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/examples/DashboardPreview.tsx @@ -0,0 +1,306 @@ +import React from "react"; +import { + DxcContainer, + DxcFlex, + DxcTypography, + DxcHeading, + DxcInset, + DxcSpinner, + DxcDivider, + DxcButton, + DxcApplicationLayout, +} from "@dxc-technology/halstack-react"; +import { Logos } from "screens/theme-generator/types"; + +const DashboardPreview = ({ logos }: { logos: Logos }) => { + return ( + + } + > + + + + + + + + + + + + + + + + Uptime over the last 24 hours + + + + + + + + + + 0 + + + Detected outages in the last 24 hours + + + + + + + + +
+ + + + + + + + + N/A + + + 95th pctl. response time + + + + + + + + N/A + + Avg actions per session + + + + N/A + + Bounce rate + + + + N/A + + User sessions + + + + + +
+
+
+ + + +
+ + + + + + + + + 3 + + Total users + + + + 0 + + MFA enrollments + + + + 0 + + Login success + + + +
+
+ + +
+ + + + + + + + + N/A + + Secure API calls + + + + N/A + + API calls failed + + + +
+
+ + + + + + + + + Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas veritatis ipsa tenetur ut fugiat + ratione similique facere, vitae hic, impedit amet quasi dolore velit odit officia. Incidunt + corporis sit rem. + + + + +
+
+
+
+
+ ); +}; + +export default DashboardPreview; diff --git a/apps/website/screens/theme-generator/previews/examples/FormPreview.tsx b/apps/website/screens/theme-generator/previews/examples/FormPreview.tsx new file mode 100644 index 0000000000..bc22d020e1 --- /dev/null +++ b/apps/website/screens/theme-generator/previews/examples/FormPreview.tsx @@ -0,0 +1,125 @@ +import { + DxcButton, + DxcContainer, + DxcFlex, + DxcTextInput, + DxcHeading, + DxcTypography, + DxcApplicationLayout, + DxcAvatar, + DxcBadge, + DxcInset, +} from "@dxc-technology/halstack-react"; +import { Logos } from "screens/theme-generator/types"; + +const FormPreview = ({ logos }: { logos: Logos }) => { + return ( + + } + header={ + , + }, + { label: "Claims", icon: "assignment" }, + { label: "Documents", icon: "folder" }, + { label: "Payments", icon: "payment" }, + ]} + sideContent={ + <> + + + + } + /> + } + sidenav={ + + } + > + + + + + + + + Contact Information + + + + + + + {}} /> + {}} /> + + + + + + + + + ); +}; + +export default FormPreview; diff --git a/apps/website/screens/theme-generator/previews/examples/index.ts b/apps/website/screens/theme-generator/previews/examples/index.ts new file mode 100644 index 0000000000..68534b58bd --- /dev/null +++ b/apps/website/screens/theme-generator/previews/examples/index.ts @@ -0,0 +1,3 @@ +export { default as ApplicationPreview } from "./ApplicationPreview"; +export { default as DashboardPreview } from "./DashboardPreview"; +export { default as FormPreview } from "./FormPreview"; diff --git a/apps/website/screens/theme-generator/steps/BrandingDetails.tsx b/apps/website/screens/theme-generator/steps/BrandingDetails.tsx new file mode 100644 index 0000000000..ce4d00534b --- /dev/null +++ b/apps/website/screens/theme-generator/steps/BrandingDetails.tsx @@ -0,0 +1,90 @@ +import { DxcContainer, DxcFlex } from "@dxc-technology/halstack-react"; +import { FileData } from "../../../../../packages/lib/src/file-input/types"; +import { Colors, Logos } from "../types"; +import BrandingLogoGrid from "../components/branding/BrandingLogoGrid"; +import { brandingIcon, infoIcon, paletteIcon } from "./icons"; +import BrandingColorGrid from "../components/branding/BrandingColorGrid"; + +const coreColors = { + id: "core", + title: "Core colors", + icon: paletteIcon, + fields: [ + { id: "primary" as const, label: "Primary", helperText: "Main brand actions" }, + { id: "secondary" as const, label: "Secondary", helperText: "Supporting interactions" }, + { id: "tertiary" as const, label: "Tertiary", helperText: "Accents and highlights" }, + { id: "neutral" as const, label: "Neutral", helperText: "Backgrounds and text" }, + ], +}; + +const semanticColors = { + id: "semantic", + title: "Semantic colors", + icon: infoIcon, + fields: [ + { id: "info" as const, label: "Info", helperText: "Informational feedback" }, + { id: "success" as const, label: "Success", helperText: "Positive outcomes" }, + { id: "error" as const, label: "Error", helperText: "Errors and failures" }, + { id: "warning" as const, label: "Warning", helperText: "Alerts and cautions" }, + ], +}; + +const brandingDetails = { + id: "logos", + title: "Branding details", + icon: brandingIcon, + fields: [ + { id: "mainLogo" as const, label: "Main logo", helperText: "Primary brand logo across the application" }, + { id: "footerLogo" as const, label: "Default footer logo", helperText: "Default variant of the footer" }, + { + id: "footerReducedLogo" as const, + label: "Reduced footer logo", + helperText: "For cluttered interfaces with reduced footer", + }, + { id: "favicon" as const, label: "Favicon", helperText: "For browser tabs and bookmarks" }, + ], +}; + +export const BrandingDetails = ({ + colors, + onColorsChange, + logos, + onLogosChange, +}: { + colors: Colors; + onColorsChange: (colors: Colors) => void; + logos: Logos; + onLogosChange: (logos: Logos) => void; +}) => { + const handleColorChange = (colorType: string) => (newColor: string) => { + onColorsChange({ + ...colors, + [colorType]: newColor, + }); + }; + + const updateLogoValue = (logoType: string, files: FileData[]) => { + onLogosChange({ + ...logos, + [logoType]: files, + }); + }; + return ( + + + + + + + + + + ); +}; diff --git a/apps/website/screens/theme-generator/steps/ReviewDetails.tsx b/apps/website/screens/theme-generator/steps/ReviewDetails.tsx new file mode 100644 index 0000000000..2fa9341863 --- /dev/null +++ b/apps/website/screens/theme-generator/steps/ReviewDetails.tsx @@ -0,0 +1,49 @@ +import { DxcButton, DxcFlex, DxcGrid, DxcTypography } from "@dxc-technology/halstack-react"; +import { Logos, Tokens } from "../types"; +import ReviewTokensGrid from "../components/review/ReviewTokensGrid"; +import ReviewTokensList from "../components/review/ReviewTokensList"; +import ReviewBrandingAssets from "../components/review/ReviewBrandingAssets"; +import useCopyToClipboard from "hooks/useCopyToClipboard"; +import ReviewSectionContainer from "../components/review/ReviewSectionContainer"; + +const ReviewDetails = ({ tokens, logos, themeJson }: { tokens: Tokens; logos: Logos; themeJson: string }) => { + const handleCopy = useCopyToClipboard(); + + return ( + <> + + + Color palette & theme + + handleCopy(themeJson)} + /> + + } + > + + + + + + + + + Branding assets + + } + > + + + + ); +}; + +export default ReviewDetails; diff --git a/apps/website/screens/theme-generator/steps/icons.tsx b/apps/website/screens/theme-generator/steps/icons.tsx new file mode 100644 index 0000000000..844b4d79b6 --- /dev/null +++ b/apps/website/screens/theme-generator/steps/icons.tsx @@ -0,0 +1,31 @@ +export const paletteIcon = ( + + + + + + + + +); + +export const infoIcon = ( + + + + +); + +export const brandingIcon = ( + + + + +); diff --git a/apps/website/screens/theme-generator/types.ts b/apps/website/screens/theme-generator/types.ts new file mode 100644 index 0000000000..52643f0e7f --- /dev/null +++ b/apps/website/screens/theme-generator/types.ts @@ -0,0 +1,64 @@ +import { CssColor } from "@adobe/leonardo-contrast-colors"; +import { ReactNode } from "react"; + +export type Tokens = Record; +export type BaseColors = Record; + +export type Step = 0 | 1 | 2; + +export type Colors = { + primary: CssColor; + secondary: CssColor; + tertiary: CssColor; + neutral: CssColor; + info: CssColor; + success: CssColor; + error: CssColor; + warning: CssColor; +}; + +export type TokenGroups = { + primary: string[]; + secondary: string[]; + tertiary: string[]; + semantic01: string[]; + semantic02: string[]; + semantic03: string[]; + semantic04: string[]; + neutral: string[]; + alpha: string[]; +}; + +export type FileData = { + error?: string; + file: File; + preview?: string; +}; + +export type Logos = { + mainLogo: FileData[]; + footerLogo: FileData[]; + footerReducedLogo: FileData[]; + favicon: FileData[]; +}; + +export type Field = { + id: string; + label: string; + helperText: string; +}; + +export type BrandingDetailsSection = { + id: string; + title: string; + icon: ReactNode; + fields: Field[]; +}; + +export type ComponentItem = { + label: string; + icon?: string; + path?: string; + status?: string; + links?: ComponentItem[]; +}; diff --git a/apps/website/screens/theme-generator/utils.ts b/apps/website/screens/theme-generator/utils.ts new file mode 100644 index 0000000000..e9830f8bf0 --- /dev/null +++ b/apps/website/screens/theme-generator/utils.ts @@ -0,0 +1,131 @@ +import { Color, BackgroundColor, Theme, type CssColor } from "@adobe/leonardo-contrast-colors"; +import { BaseColors, TokenGroups, Tokens } from "./types"; + +/** + * Contrast ratios for generating color shades + * Based on WCAG accessibility standards + */ +export const CONTRAST_RATIOS = [1.03, 1.18, 1.34, 1.52, 2.04, 2.79, 4.3, 6.7, 9, 12.46]; + +/** + * Shade values corresponding to each contrast ratio (50-900) + */ +export const SHADE_VALUES = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]; + +const ALPHA_VALUES = ["1a", "33", "4d", "66", "80", "99", "b2", "cc", "e5"]; + +/** + * Generate a full color palette (50-900 shades) from a base hex color + * Uses Adobe Leonardo to ensure accessible contrast ratios + */ + +export const generatePalette = (hex: CssColor): string[] => { + try { + const bg = new BackgroundColor({ + name: "bg", + colorKeys: ["#fff"], + ratios: CONTRAST_RATIOS, + }); + const color = new Color({ + name: "custom", + colorKeys: [hex], + ratios: CONTRAST_RATIOS, + colorSpace: "LCH", + smooth: false, + }); + const theme = new Theme({ + colors: [color], + backgroundColor: bg, + lightness: 97, + }); + + return theme.contrastColors[1]?.values?.map((v) => v.value) || []; + } catch (error) { + console.error("Error generating palette for hex:", hex, error); + return []; + } +}; + +const generateAlphaColorsObject = (neutralPalette: string[]): Tokens => { + const neutralColorsFrom100 = neutralPalette.slice(1, 10); + const alphaObj: Tokens = {}; + + neutralColorsFrom100.forEach((neutralColor, i) => { + const key = `--color-alpha-${(i + 1) * 100}-a`; + alphaObj[key] = `${neutralColor}${ALPHA_VALUES[i]}`; + }); + + return alphaObj; +}; + +const generateAbsolutesObject = (): Tokens => ({ + "--color-absolutes-black": "#000000", + "--color-absolutes-white": "#ffffff", +}); + +const generateTokensObject = (baseColors: BaseColors): Tokens => { + const neutralColor = baseColors.Neutral || "#999999"; + const neutralPalette = generatePalette(neutralColor); + //For each base color, generate its palette + //and create an object with the tokens + //in the format color__ + //where is the color name in lowercase + //and is the palette value (50, 100, 200, etc.) + //Example: color_primary_50, color_primary_100, + const baseTokensObj: Tokens = {}; + Object.entries(baseColors).forEach(([name, hex]) => { + const palette = generatePalette(hex); + palette.forEach((color, i) => { + const key = `--color-${name.toLowerCase()}-${SHADE_VALUES[i]}`; + baseTokensObj[key] = color; + }); + }); + + const alphaObj = generateAlphaColorsObject(neutralPalette); + const absolutesObj = generateAbsolutesObject(); + + const allTokensObj = { ...baseTokensObj, ...alphaObj, ...absolutesObj }; + + return allTokensObj; +}; + +export const generateTokens = (baseColors: BaseColors): Tokens => { + return generateTokensObject(baseColors); +}; + +export const handleExport = (themeJson: string) => { + const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(themeJson); + const downloadAnchorNode = document.createElement("a"); + downloadAnchorNode.setAttribute("href", dataStr); + downloadAnchorNode.setAttribute("download", "halstack-theme-tokens.json"); + document.body.appendChild(downloadAnchorNode); + downloadAnchorNode.click(); + downloadAnchorNode.remove(); +}; + +export const divideColorTokens = (tokens: Tokens) => { + const groups: TokenGroups = { + primary: [], + secondary: [], + tertiary: [], + semantic01: [], + semantic02: [], + semantic03: [], + semantic04: [], + neutral: [], + alpha: [], + }; + + for (const [key, value] of Object.entries(tokens)) { + // divides tokens names into 3 sections + const sections = key.match(/^--color-([a-z0-9]+)-(.+)$/); + if (sections) { + // the second section indicates the group (primary, secondary, etc.) + const group = sections[1]; + if (group && group in groups) { + groups[group as keyof TokenGroups].push(value); + } + } + } + return groups; +}; diff --git a/apps/website/screens/utilities/halstack-provider/HalstackProviderPage.tsx b/apps/website/screens/utilities/halstack-provider/HalstackProviderPage.tsx index b47a212d4a..7660e3603a 100644 --- a/apps/website/screens/utilities/halstack-provider/HalstackProviderPage.tsx +++ b/apps/website/screens/utilities/halstack-provider/HalstackProviderPage.tsx @@ -71,7 +71,7 @@ const sections = [ text: ( <> To find out the list of labels that are translatable we should refer to the documentation in the{" "} - + Localization {" "} section. @@ -109,6 +109,14 @@ const sections = [ want and their respective values. Then we pass one of the objects based on the state of the theme{" "} to the Halstack Provider, which wraps our components, through its opinionatedTheme property. + + Themes can be created with the{" "} + + Theme Generator + {" "} + tool, which allows you to define your brand colors and export a ready-to-use token structure to pass through + the opinionatedTheme property. + ), }, diff --git a/package-lock.json b/package-lock.json index 64052cc77b..1090b96f44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ }, "apps/website": { "dependencies": { + "@adobe/leonardo-contrast-colors": "^1.0.0", "@cloudscape-design/components": "^3.0.706", "@dxc-technology/halstack-react": "*", "@emotion/cache": "^11.14.0", @@ -66,6 +67,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@adobe/leonardo-contrast-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@adobe/leonardo-contrast-colors/-/leonardo-contrast-colors-1.1.0.tgz", + "integrity": "sha512-URFR8vNgNsE/rnXqljVrx6OyZV3nQXTfbDDWZwTUYfOkmBr9hRB7ENK8f7pT7gHDjSuCf2bjJ227u4PUHUXHHg==", + "license": "Apache-2.0", + "dependencies": { + "apca-w3": "^0.1.9", + "chroma-js": "^3.2.0", + "ciebase": "^0.1.1", + "ciecam02": "^0.4.6", + "hsluv": "^1.0.1" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -2115,9 +2129,9 @@ } }, "node_modules/@cloudscape-design/component-toolkit": { - "version": "1.0.0-beta.140", - "resolved": "https://registry.npmjs.org/@cloudscape-design/component-toolkit/-/component-toolkit-1.0.0-beta.140.tgz", - "integrity": "sha512-gzA0azSM/uyT4HOOWZ4I09Gb+uIO+BLOvIwQzUNYRU1xOSMp60duVa0KvN14suKwaYUIwyGK3GSLK6MyoT65Jw==", + "version": "1.0.0-beta.141", + "resolved": "https://registry.npmjs.org/@cloudscape-design/component-toolkit/-/component-toolkit-1.0.0-beta.141.tgz", + "integrity": "sha512-OkUfNVJB1NGfBWpodn/E6Y+ZO2FyNVXzDk4e0EKmcZW5Dof3zO6GlZgJVBSIU4NtlDq7rO0Ze13PsMWWgzHZTQ==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1", @@ -2134,9 +2148,9 @@ "license": "MIT" }, "node_modules/@cloudscape-design/components": { - "version": "3.0.1225", - "resolved": "https://registry.npmjs.org/@cloudscape-design/components/-/components-3.0.1225.tgz", - "integrity": "sha512-bSg9MWIQ/JoSQPQg7xwivKOXn8qs/sqltCNRHghYP4lhPveBQ6w1Q1ULulHVM7wTeRQlkCQxPhkNHyhr4tdchw==", + "version": "3.0.1228", + "resolved": "https://registry.npmjs.org/@cloudscape-design/components/-/components-3.0.1228.tgz", + "integrity": "sha512-wV4JNHByjJ21Y673jdCBMQzE9+YmYev7omZ0PkI8VDDwRgBioR3ygtdLLrVbZ9WyqN9fy5ZlTqZX/hUkf1azjA==", "license": "Apache-2.0", "dependencies": { "@cloudscape-design/collection-hooks": "^1.0.0", @@ -3995,17 +4009,17 @@ } }, "node_modules/@jest/console": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", - "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.3.0.tgz", + "integrity": "sha512-PAwCvFJ4696XP2qZj+LAn1BWjZaJ6RjG6c7/lkMaUJnkyMS34ucuIsfqYvfskVNvUI27R/u4P1HMYFnlVXG/Ww==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", "slash": "^3.0.0" }, "engines": { @@ -4026,19 +4040,19 @@ } }, "node_modules/@jest/console/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -4047,27 +4061,27 @@ } }, "node_modules/@jest/console/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/console/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4087,39 +4101,38 @@ "license": "MIT" }, "node_modules/@jest/core": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", - "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.3.0.tgz", + "integrity": "sha512-U5mVPsBxLSO6xYbf+tgkymLx+iAhvZX43/xI1+ej2ZOPnPdkdO1CzDmFKh2mZBn2s4XZixszHeQnzp1gm/DIxw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.2.0", + "@jest/console": "30.3.0", "@jest/pattern": "30.0.1", - "@jest/reporters": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/reporters": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "ci-info": "^4.2.0", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", - "jest-changed-files": "30.2.0", - "jest-config": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", + "jest-changed-files": "30.3.0", + "jest-config": "30.3.0", + "jest-haste-map": "30.3.0", + "jest-message-util": "30.3.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-resolve-dependencies": "30.2.0", - "jest-runner": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "jest-watcher": "30.2.0", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "jest-resolve": "30.3.0", + "jest-resolve-dependencies": "30.3.0", + "jest-runner": "30.3.0", + "jest-runtime": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", + "jest-watcher": "30.3.0", + "pretty-format": "30.3.0", "slash": "^3.0.0" }, "engines": { @@ -4148,19 +4161,19 @@ } }, "node_modules/@jest/core/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -4169,27 +4182,27 @@ } }, "node_modules/@jest/core/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/core/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4209,9 +4222,9 @@ "license": "MIT" }, "node_modules/@jest/diff-sequences": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", - "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.3.0.tgz", + "integrity": "sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==", "dev": true, "license": "MIT", "engines": { @@ -4219,16 +4232,16 @@ } }, "node_modules/@jest/environment": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", - "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.3.0.tgz", + "integrity": "sha512-SlLSF4Be735yQXyh2+mctBOzNDx5s5uLv88/j8Qn1wH679PDcwy67+YdADn8NJnGjzlXtN62asGH/T4vWOkfaw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", + "@jest/fake-timers": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-mock": "30.2.0" + "jest-mock": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -4281,14 +4294,14 @@ } }, "node_modules/@jest/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-76Nlh4xJxk2D/9URCn3wFi98d2hb19uWE1idLsTt2ywhvdOldbw3S570hBgn25P4ICUZ/cBjybrBex2g17IDbg==", "dev": true, "license": "MIT", "dependencies": { - "expect": "30.2.0", - "jest-snapshot": "30.2.0" + "expect": "30.3.0", + "jest-snapshot": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -4308,9 +4321,9 @@ } }, "node_modules/@jest/expect/node_modules/@jest/expect-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", - "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.3.0.tgz", + "integrity": "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==", "dev": true, "license": "MIT", "dependencies": { @@ -4334,69 +4347,69 @@ } }, "node_modules/@jest/expect/node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.2.0", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect/node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", + "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", + "@jest/diff-sequences": "30.3.0", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect/node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", + "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" + "jest-diff": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -4405,27 +4418,27 @@ } }, "node_modules/@jest/expect/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4445,18 +4458,18 @@ "license": "MIT" }, "node_modules/@jest/fake-timers": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", - "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.3.0.tgz", + "integrity": "sha512-WUQDs8SOP9URStX1DzhD425CqbN/HxUYCTwVrT8sTVBfMvFqYt/s61EK5T05qnHu0po6RitXIvP9otZxYDzTGQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@sinonjs/fake-timers": "^13.0.0", + "@jest/types": "30.3.0", + "@sinonjs/fake-timers": "^15.0.0", "@types/node": "*", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -4476,19 +4489,19 @@ } }, "node_modules/@jest/fake-timers/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -4497,27 +4510,27 @@ } }, "node_modules/@jest/fake-timers/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/fake-timers/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4547,16 +4560,16 @@ } }, "node_modules/@jest/globals": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", - "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.3.0.tgz", + "integrity": "sha512-+owLCBBdfpgL3HU+BD5etr1SvbXpSitJK0is1kiYjJxAAJggYMRQz5hSdd5pq1sSggfxPbw2ld71pt4x5wwViA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/types": "30.2.0", - "jest-mock": "30.2.0" + "@jest/environment": "30.3.0", + "@jest/expect": "30.3.0", + "@jest/types": "30.3.0", + "jest-mock": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -4577,32 +4590,32 @@ } }, "node_modules/@jest/reporters": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", - "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.3.0.tgz", + "integrity": "sha512-a09z89S+PkQnL055bVj8+pe2Caed2PBOaczHcXCykW5ngxX9EWx/1uAwncxc/HiU0oZqfwseMjyhxgRjS49qPw==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/console": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@jridgewell/trace-mapping": "^0.3.25", "@types/node": "*", "chalk": "^4.1.2", "collect-v8-coverage": "^1.0.2", "exit-x": "^0.2.2", - "glob": "^10.3.10", + "glob": "^10.5.0", "graceful-fs": "^4.2.11", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^5.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", + "jest-worker": "30.3.0", "slash": "^3.0.0", "string-length": "^4.0.2", "v8-to-istanbul": "^9.0.1" @@ -4640,19 +4653,19 @@ } }, "node_modules/@jest/reporters/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -4661,27 +4674,27 @@ } }, "node_modules/@jest/reporters/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/reporters/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4714,13 +4727,13 @@ } }, "node_modules/@jest/snapshot-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", - "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.3.0.tgz", + "integrity": "sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "natural-compare": "^1.4.0" @@ -4745,14 +4758,14 @@ } }, "node_modules/@jest/test-result": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", - "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.3.0.tgz", + "integrity": "sha512-e/52nJGuD74AKTSe0P4y5wFRlaXP0qmrS17rqOMHeSwm278VyNyXE3gFO/4DTGF9w+65ra3lo3VKj0LBrzmgdQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.2.0", - "@jest/types": "30.2.0", + "@jest/console": "30.3.0", + "@jest/types": "30.3.0", "@types/istanbul-lib-coverage": "^2.0.6", "collect-v8-coverage": "^1.0.2" }, @@ -4761,15 +4774,15 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", - "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.3.0.tgz", + "integrity": "sha512-dgbWy9b8QDlQeRZcv7LNF+/jFiiYHTKho1xirauZ7kVwY7avjFF6uTT0RqlgudB5OuIPagFdVtfFMosjVbk1eA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.2.0", + "@jest/test-result": "30.3.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", + "jest-haste-map": "30.3.0", "slash": "^3.0.0" }, "engines": { @@ -4777,24 +4790,23 @@ } }, "node_modules/@jest/transform": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", - "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.3.0.tgz", + "integrity": "sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@jridgewell/trace-mapping": "^0.3.25", "babel-plugin-istanbul": "^7.0.1", "chalk": "^4.1.2", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", + "jest-haste-map": "30.3.0", "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "micromatch": "^4.0.8", + "jest-util": "30.3.0", "pirates": "^4.0.7", "slash": "^3.0.0", "write-file-atomic": "^5.0.1" @@ -4804,27 +4816,27 @@ } }, "node_modules/@jest/transform/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/types": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", - "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz", + "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==", "dev": true, "license": "MIT", "dependencies": { @@ -6083,9 +6095,9 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.1.1.tgz", + "integrity": "sha512-cO5W33JgAPbOh07tvZjUOJ7oWhtaqGHiZw+11DPbyqh2kHTBc3eF/CjJDeQ4205RLQsX6rxCuYOroFQwl7JDRw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -6841,17 +6853,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz", - "integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.0.tgz", + "integrity": "sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/type-utils": "8.56.1", - "@typescript-eslint/utils": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/type-utils": "8.57.0", + "@typescript-eslint/utils": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" @@ -6864,7 +6876,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.56.1", + "@typescript-eslint/parser": "^8.57.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } @@ -6880,16 +6892,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", - "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.57.0.tgz", + "integrity": "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3" }, "engines": { @@ -6905,14 +6917,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", - "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.0.tgz", + "integrity": "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.56.1", - "@typescript-eslint/types": "^8.56.1", + "@typescript-eslint/tsconfig-utils": "^8.57.0", + "@typescript-eslint/types": "^8.57.0", "debug": "^4.4.3" }, "engines": { @@ -6927,14 +6939,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", - "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.0.tgz", + "integrity": "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1" + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6945,9 +6957,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", - "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.0.tgz", + "integrity": "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==", "dev": true, "license": "MIT", "engines": { @@ -6962,15 +6974,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz", - "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.57.0.tgz", + "integrity": "sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/utils": "8.56.1", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0", + "@typescript-eslint/utils": "8.57.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, @@ -6987,9 +6999,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", - "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.0.tgz", + "integrity": "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==", "dev": true, "license": "MIT", "engines": { @@ -7001,16 +7013,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", - "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.0.tgz", + "integrity": "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.56.1", - "@typescript-eslint/tsconfig-utils": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/project-service": "8.57.0", + "@typescript-eslint/tsconfig-utils": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -7081,16 +7093,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", - "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.0.tgz", + "integrity": "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1" + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7105,13 +7117,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", - "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.0.tgz", + "integrity": "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -8022,6 +8034,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/apca-w3": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/apca-w3/-/apca-w3-0.1.9.tgz", + "integrity": "sha512-Zrf6AeBeQjNe/fxK7U1jCo5zfdjDl6T4/kdw5Xlky3G7u+EJTZkyItjMYQGtwf9pkftsINxcYyOpuLkzKf1ITQ==", + "license": "Limited W3 License", + "dependencies": { + "colorparsley": "^0.1.8" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -8324,16 +8345,16 @@ } }, "node_modules/babel-jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz", - "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.3.0.tgz", + "integrity": "sha512-gRpauEU2KRrCox5Z296aeVHR4jQ98BCnu0IO332D/xpHNOsIH/bgSRk9k6GbKIbBw8vFeN6ctuu6tV8WOyVfYQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/transform": "30.2.0", + "@jest/transform": "30.3.0", "@types/babel__core": "^7.20.5", "babel-plugin-istanbul": "^7.0.1", - "babel-preset-jest": "30.2.0", + "babel-preset-jest": "30.3.0", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "slash": "^3.0.0" @@ -8403,9 +8424,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", - "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.3.0.tgz", + "integrity": "sha512-+TRkByhsws6sfPjVaitzadk1I0F5sPvOVUH5tyTSzhePpsGIVrdeunHSw/C36QeocS95OOk8lunc4rlu5Anwsg==", "dev": true, "license": "MIT", "dependencies": { @@ -8500,13 +8521,13 @@ } }, "node_modules/babel-preset-jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", - "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.3.0.tgz", + "integrity": "sha512-6ZcUbWHC+dMz2vfzdNwi87Z1gQsLNK2uLuK1Q89R11xdvejcivlYYwDlEv0FHX3VwEXpbBQ9uufB/MUNpZGfhQ==", "dev": true, "license": "MIT", "dependencies": { - "babel-plugin-jest-hoist": "30.2.0", + "babel-plugin-jest-hoist": "30.3.0", "babel-preset-current-node-syntax": "^1.2.0" }, "engines": { @@ -8835,6 +8856,12 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/chroma-js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-3.2.0.tgz", + "integrity": "sha512-os/OippSlX1RlWWr+QDPcGUZs0uoqr32urfxESG9U93lhUfbnlyckte84Q8P1UQY/qth983AS1JONKmLS4T0nw==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, "node_modules/chromatic": { "version": "13.3.5", "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-13.3.5.tgz", @@ -8885,6 +8912,25 @@ "node": ">=8" } }, + "node_modules/ciebase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ciebase/-/ciebase-0.1.1.tgz", + "integrity": "sha512-KEnf/WVT5E+Gn+LsfMHGJFATltSOeW0qm7dpzQYL/Qe5PEpyTM+UI5bMoBo16FE81zMpu+U6032USTP6Cz1XNA==", + "license": "BSD-2-Clause", + "dependencies": { + "mout": "^0.11.1" + } + }, + "node_modules/ciecam02": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/ciecam02/-/ciecam02-0.4.6.tgz", + "integrity": "sha512-nh/Kl8s5lgtyEl7lA381JFinLhgUwDhJaAVgbVx2BaiiJIzJLumQvuFXwdS76tSch7jDjWejP+MtKYCCEk/brg==", + "license": "BSD-2-Clause", + "dependencies": { + "ciebase": "^0.1.1", + "mout": "^0.11.1" + } + }, "node_modules/cjs-module-lexer": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", @@ -9109,6 +9155,12 @@ "dev": true, "license": "MIT" }, + "node_modules/colorparsley": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/colorparsley/-/colorparsley-0.1.8.tgz", + "integrity": "sha512-rObESTTTE6G5qO5WFwFxWPggpw4KfpxnLC6Ssl8bITBnNVRhDsyCeTRAUxWQNVTx2pRknKlO2nddYTxjkdNFaw==", + "license": "AGPL v3" + }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -10174,13 +10226,13 @@ } }, "node_modules/eslint-config-turbo": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/eslint-config-turbo/-/eslint-config-turbo-2.8.14.tgz", - "integrity": "sha512-WYB0jwiITLpiWx42J7p1XNSAzRxAwmX9qpRBCIH4+R/9mgp72o8GtUKLX8vgxK4c8Vwqiedv4MqPwDxJurrVWQ==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/eslint-config-turbo/-/eslint-config-turbo-2.8.16.tgz", + "integrity": "sha512-7JY6vlgFZWUH1YlLpxQjgia3bjcIpWxYahDQ/XfXSU5etv2KyEPY/O6jK/8Tg+Z2xjZm8ZQFgqK15K5MLIQAFA==", "dev": true, "license": "MIT", "dependencies": { - "eslint-plugin-turbo": "2.8.14" + "eslint-plugin-turbo": "2.8.16" }, "peerDependencies": { "eslint": ">6.6.0", @@ -10564,9 +10616,9 @@ } }, "node_modules/eslint-plugin-turbo": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-2.8.14.tgz", - "integrity": "sha512-AU3H0trwN9AoDZHHIx+TWSLc/AXIqk0iB93dy5zF5EmhAS3KTVPlFRJHWXc4BdKo8gy/Z11DKrZZQTpqIZ8k4A==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-2.8.16.tgz", + "integrity": "sha512-fhvTLe0PnyV72npfBi/IwwVMzkTnUw9MxS2S2Q0Oo1aed7woAtHwSL5DEdTTV6tXZSKbqRHaIbjV6rwx+1iRYA==", "dev": true, "license": "MIT", "dependencies": { @@ -11541,6 +11593,12 @@ "react-is": "^16.7.0" } }, + "node_modules/hsluv": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hsluv/-/hsluv-1.0.1.tgz", + "integrity": "sha512-zCaFTiDqBLQjCCFBu0qg7z9ASYPd+Bxx2GDCVZJsnehjK80S+jByqhuFz0pCd2Aw3FSKr18AWbRlwnKR0YdizQ==", + "license": "MIT" + }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -12439,16 +12497,16 @@ } }, "node_modules/jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", - "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.3.0.tgz", + "integrity": "sha512-AkXIIFcaazymvey2i/+F94XRnM6TsVLZDhBMLsd1Sf/W0wzsvvpjeyUrCZD6HGG4SDYPgDJDBKeiJTBb10WzMg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.2.0", - "@jest/types": "30.2.0", + "@jest/core": "30.3.0", + "@jest/types": "30.3.0", "import-local": "^3.2.0", - "jest-cli": "30.2.0" + "jest-cli": "30.3.0" }, "bin": { "jest": "bin/jest.js" @@ -12466,14 +12524,14 @@ } }, "node_modules/jest-changed-files": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", - "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.3.0.tgz", + "integrity": "sha512-B/7Cny6cV5At6M25EWDgf9S617lHivamL8vl6KEpJqkStauzcG4e+WPfDgMMF+H4FVH4A2PLRyvgDJan4441QA==", "dev": true, "license": "MIT", "dependencies": { "execa": "^5.1.1", - "jest-util": "30.2.0", + "jest-util": "30.3.0", "p-limit": "^3.1.0" }, "engines": { @@ -12481,47 +12539,47 @@ } }, "node_modules/jest-changed-files/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-circus": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", - "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.3.0.tgz", + "integrity": "sha512-PyXq5szeSfR/4f1lYqCmmQjh0vqDkURUYi9N6whnHjlRz4IUQfMcXkGLeEoiJtxtyPqgUaUUfyQlApXWBSN1RA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/environment": "30.3.0", + "@jest/expect": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "co": "^4.6.0", "dedent": "^1.6.0", "is-generator-fn": "^2.1.0", - "jest-each": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", + "jest-each": "30.3.0", + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-runtime": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", "p-limit": "^3.1.0", - "pretty-format": "30.2.0", + "pretty-format": "30.3.0", "pure-rand": "^7.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" @@ -12544,51 +12602,51 @@ } }, "node_modules/jest-circus/node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", + "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", + "@jest/diff-sequences": "30.3.0", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-circus/node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", + "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" + "jest-diff": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-circus/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -12597,27 +12655,27 @@ } }, "node_modules/jest-circus/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-circus/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12637,21 +12695,21 @@ "license": "MIT" }, "node_modules/jest-cli": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", - "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.3.0.tgz", + "integrity": "sha512-l6Tqx+j1fDXJEW5bqYykDQQ7mQg+9mhWXtnj+tQZrTWYHyHoi6Be8HPumDSA+UiX2/2buEgjA58iJzdj146uCw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/core": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", "chalk": "^4.1.2", "exit-x": "^0.2.2", "import-local": "^3.2.0", - "jest-config": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", + "jest-config": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", "yargs": "^17.7.2" }, "bin": { @@ -12670,52 +12728,51 @@ } }, "node_modules/jest-cli/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-config": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", - "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.3.0.tgz", + "integrity": "sha512-WPMAkMAtNDY9P/oKObtsRG/6KTrhtgPJoBTmk20uDn4Uy6/3EJnnaZJre/FMT1KVRx8cve1r7/FlMIOfRVWL4w==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", "@jest/get-type": "30.1.0", "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.2.0", - "@jest/types": "30.2.0", - "babel-jest": "30.2.0", + "@jest/test-sequencer": "30.3.0", + "@jest/types": "30.3.0", + "babel-jest": "30.3.0", "chalk": "^4.1.2", "ci-info": "^4.2.0", "deepmerge": "^4.3.1", - "glob": "^10.3.10", + "glob": "^10.5.0", "graceful-fs": "^4.2.11", - "jest-circus": "30.2.0", + "jest-circus": "30.3.0", "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", + "jest-environment-node": "30.3.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-runner": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "micromatch": "^4.0.8", + "jest-resolve": "30.3.0", + "jest-runner": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", "parse-json": "^5.2.0", - "pretty-format": "30.2.0", + "pretty-format": "30.3.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -12753,27 +12810,27 @@ } }, "node_modules/jest-config/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-config/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12877,17 +12934,17 @@ } }, "node_modules/jest-each": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", - "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.3.0.tgz", + "integrity": "sha512-V8eMndg/aZ+3LnCJgSm13IxS5XSBM22QSZc9BtPK8Dek6pm+hfUNfwBdvsB3d342bo1q7wnSkC38zjX259qZNA==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "chalk": "^4.1.2", - "jest-util": "30.2.0", - "pretty-format": "30.2.0" + "jest-util": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -12907,27 +12964,27 @@ } }, "node_modules/jest-each/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-each/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12947,16 +13004,14 @@ "license": "MIT" }, "node_modules/jest-environment-jsdom": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-30.2.0.tgz", - "integrity": "sha512-zbBTiqr2Vl78pKp/laGBREYzbZx9ZtqPjOK4++lL4BNDhxRnahg51HtoDrk9/VjIy9IthNEWdKVd7H5bqBhiWQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-30.3.0.tgz", + "integrity": "sha512-RLEOJy6ip1lpw0yqJ8tB3i88FC7VBz7i00Zvl2qF71IdxjS98gC9/0SPWYIBVXHm5hgCYK0PAlSlnHGGy9RoMg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/environment-jsdom-abstract": "30.2.0", - "@types/jsdom": "^21.1.7", - "@types/node": "*", + "@jest/environment": "30.3.0", + "@jest/environment-jsdom-abstract": "30.3.0", "jsdom": "^26.1.0" }, "engines": { @@ -12972,37 +13027,37 @@ } }, "node_modules/jest-environment-node": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", - "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.3.0.tgz", + "integrity": "sha512-4i6HItw/JSiJVsC5q0hnKIe/hbYfZLVG9YJ/0pU9Hz2n/9qZe3Rhn5s5CUZA5ORZlcdT/vmAXRMyONXJwPrmYQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", + "@jest/environment": "30.3.0", + "@jest/fake-timers": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-mock": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0" + "jest-mock": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-environment-node/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -13019,21 +13074,21 @@ } }, "node_modules/jest-haste-map": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", - "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.3.0.tgz", + "integrity": "sha512-mMi2oqG4KRU0R9QEtscl87JzMXfUhbKaFqOxmjb2CKcbHcUGFrJCBWHmnTiUqi6JcnzoBlO4rWfpdl2k/RfLCA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "anymatch": "^3.1.3", "fb-watchman": "^2.0.2", "graceful-fs": "^4.2.11", "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", - "micromatch": "^4.0.8", + "jest-util": "30.3.0", + "jest-worker": "30.3.0", + "picomatch": "^4.0.3", "walker": "^1.0.8" }, "engines": { @@ -13044,32 +13099,32 @@ } }, "node_modules/jest-haste-map/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-leak-detector": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", - "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.3.0.tgz", + "integrity": "sha512-cuKmUUGIjfXZAiGJ7TbEMx0bcqNdPPI6P1V+7aF+m/FUJqFDxkFR4JqkTu8ZOiU5AaX/x0hZ20KaaIPXQzbMGQ==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -13089,9 +13144,9 @@ } }, "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13276,33 +13331,33 @@ "license": "MIT" }, "node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.3.0.tgz", + "integrity": "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-util": "30.2.0" + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-mock/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -13337,18 +13392,18 @@ } }, "node_modules/jest-resolve": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", - "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.3.0.tgz", + "integrity": "sha512-NRtTAHQlpd15F9rUR36jqwelbrDV/dY4vzNte3S2kxCKUJRYNd5/6nTSbYiak1VX5g8IoFF23Uj5TURkUW8O5g==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", + "jest-haste-map": "30.3.0", "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", "slash": "^3.0.0", "unrs-resolver": "^1.7.11" }, @@ -13357,64 +13412,64 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", - "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.3.0.tgz", + "integrity": "sha512-9ev8s3YN6Hsyz9LV75XUwkCVFlwPbaFn6Wp75qnI0wzAINYWY8Fb3+6y59Rwd3QaS3kKXffHXsZMziMavfz/nw==", "dev": true, "license": "MIT", "dependencies": { "jest-regex-util": "30.0.1", - "jest-snapshot": "30.2.0" + "jest-snapshot": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-resolve/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-runner": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", - "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.3.0.tgz", + "integrity": "sha512-gDv6C9LGKWDPLia9TSzZwf4h3kMQCqyTpq+95PODnTRDO0g9os48XIYYkS6D236vjpBir2fF63YmJFtqkS5Duw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.2.0", - "@jest/environment": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/console": "30.3.0", + "@jest/environment": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "emittery": "^0.13.1", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-leak-detector": "30.2.0", - "jest-message-util": "30.2.0", - "jest-resolve": "30.2.0", - "jest-runtime": "30.2.0", - "jest-util": "30.2.0", - "jest-watcher": "30.2.0", - "jest-worker": "30.2.0", + "jest-environment-node": "30.3.0", + "jest-haste-map": "30.3.0", + "jest-leak-detector": "30.3.0", + "jest-message-util": "30.3.0", + "jest-resolve": "30.3.0", + "jest-runtime": "30.3.0", + "jest-util": "30.3.0", + "jest-watcher": "30.3.0", + "jest-worker": "30.3.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -13436,19 +13491,19 @@ } }, "node_modules/jest-runner/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -13457,27 +13512,27 @@ } }, "node_modules/jest-runner/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-runner/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13497,32 +13552,32 @@ "license": "MIT" }, "node_modules/jest-runtime": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", - "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.3.0.tgz", + "integrity": "sha512-CgC+hIBJbuh78HEffkhNKcbXAytQViplcl8xupqeIWyKQF50kCQA8J7GeJCkjisC6hpnC9Muf8jV5RdtdFbGng==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/globals": "30.2.0", + "@jest/environment": "30.3.0", + "@jest/fake-timers": "30.3.0", + "@jest/globals": "30.3.0", "@jest/source-map": "30.0.1", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "cjs-module-lexer": "^2.1.0", "collect-v8-coverage": "^1.0.2", - "glob": "^10.3.10", + "glob": "^10.5.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", + "jest-haste-map": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", + "jest-resolve": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -13544,19 +13599,19 @@ } }, "node_modules/jest-runtime/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -13565,27 +13620,27 @@ } }, "node_modules/jest-runtime/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-runtime/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13605,9 +13660,9 @@ "license": "MIT" }, "node_modules/jest-snapshot": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", - "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.3.0.tgz", + "integrity": "sha512-f14c7atpb4O2DeNhwcvS810Y63wEn8O1HqK/luJ4F6M4NjvxmAKQwBUWjbExUtMxWJQ0wVgmCKymeJK6NZMnfQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13616,20 +13671,20 @@ "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.2.0", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", - "@jest/snapshot-utils": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/snapshot-utils": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "babel-preset-current-node-syntax": "^1.2.0", "chalk": "^4.1.2", - "expect": "30.2.0", + "expect": "30.3.0", "graceful-fs": "^4.2.11", - "jest-diff": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "pretty-format": "30.2.0", + "jest-diff": "30.3.0", + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", + "pretty-format": "30.3.0", "semver": "^7.7.2", "synckit": "^0.11.8" }, @@ -13638,9 +13693,9 @@ } }, "node_modules/jest-snapshot/node_modules/@jest/expect-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", - "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.3.0.tgz", + "integrity": "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==", "dev": true, "license": "MIT", "dependencies": { @@ -13664,69 +13719,69 @@ } }, "node_modules/jest-snapshot/node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.2.0", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", + "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", + "@jest/diff-sequences": "30.3.0", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", + "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" + "jest-diff": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -13735,27 +13790,27 @@ } }, "node_modules/jest-snapshot/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13873,18 +13928,18 @@ } }, "node_modules/jest-validate": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", - "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.3.0.tgz", + "integrity": "sha512-I/xzC8h5G+SHCb2P2gWkJYrNiTbeL47KvKeW5EzplkyxzBRBw1ssSHlI/jXec0ukH2q7x2zAWQm7015iusg62Q==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "camelcase": "^6.3.0", "chalk": "^4.1.2", "leven": "^3.1.0", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -13917,9 +13972,9 @@ } }, "node_modules/jest-validate/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13939,19 +13994,19 @@ "license": "MIT" }, "node_modules/jest-watcher": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", - "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.3.0.tgz", + "integrity": "sha512-PJ1d9ThtTR8aMiBWUdcownq9mDdLXsQzJayTk4kmaBRHKvwNQn+ANveuhEBUyNI2hR1TVhvQ8D5kHubbzBHR/w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "emittery": "^0.13.1", - "jest-util": "30.2.0", + "jest-util": "30.3.0", "string-length": "^4.0.2" }, "engines": { @@ -13959,33 +14014,33 @@ } }, "node_modules/jest-watcher/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-worker": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", - "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.3.0.tgz", + "integrity": "sha512-DrCKkaQwHexjRUFTmPzs7sHQe0TSj9nvDALKGdwmK5mW9v7j90BudWirKAJHt3QQ9Dhrg1F7DogPzhChppkJpQ==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.2.0", + "jest-util": "30.3.0", "merge-stream": "^2.0.0", "supports-color": "^8.1.1" }, @@ -13994,18 +14049,18 @@ } }, "node_modules/jest-worker/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -15502,6 +15557,12 @@ "node": ">=12.13.0" } }, + "node_modules/mout": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz", + "integrity": "sha512-pK9VNiLE3QgGBrC/3ICAscwOLU7oTNeK2l32uqNAioBYtB2tQAfSsGDNChUlk7CP23126mc5lUt6+na9FlN8JA==", + "license": "MIT" + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -18808,9 +18869,9 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.17", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.17.tgz", - "integrity": "sha512-YR7PtUp6GMU91BgSJmlaX/rS2lGDbAF7D+Wtq7hRO+MiljNmodYvqslzCFiYVAgW+Qoaaia/QUIP4lGXufjdZw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", + "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", "license": "MIT", "peer": true, "dependencies": { @@ -19932,27 +19993,27 @@ } }, "node_modules/turbo": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.8.14.tgz", - "integrity": "sha512-UCTxeMNYT1cKaHiIFdLCQ7ulI+jw5i5uOnJOrRXsgUD7G3+OjlUjwVd7JfeVt2McWSVGjYA3EVW/v1FSsJ5DtA==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.8.16.tgz", + "integrity": "sha512-u6e9e3cTTpE2adQ1DYm3A3r8y3LAONEx1jYvJx6eIgSY4bMLxIxs0riWzI0Z/IK903ikiUzRPZ2c1Ph5lVLkhA==", "dev": true, "license": "MIT", "bin": { "turbo": "bin/turbo" }, "optionalDependencies": { - "turbo-darwin-64": "2.8.14", - "turbo-darwin-arm64": "2.8.14", - "turbo-linux-64": "2.8.14", - "turbo-linux-arm64": "2.8.14", - "turbo-windows-64": "2.8.14", - "turbo-windows-arm64": "2.8.14" + "turbo-darwin-64": "2.8.16", + "turbo-darwin-arm64": "2.8.16", + "turbo-linux-64": "2.8.16", + "turbo-linux-arm64": "2.8.16", + "turbo-windows-64": "2.8.16", + "turbo-windows-arm64": "2.8.16" } }, "node_modules/turbo-darwin-64": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.8.14.tgz", - "integrity": "sha512-9sFi7n2lLfEsGWi5OEoA/eTtQU2BPKtzSYKqufMtDeRmqMT9vKjbv9gJCRkllSVE9BOXA0qXC3diyX8V8rKIKw==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.8.16.tgz", + "integrity": "sha512-KWa4hUMWrpADC6Q/wIHRkBLw6X6MV9nx6X7hSXbTrrMz0KdaKhmfudUZ3sS76bJFmgArBU25cSc0AUyyrswYxg==", "cpu": [ "x64" ], @@ -19964,9 +20025,9 @@ ] }, "node_modules/turbo-darwin-arm64": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.8.14.tgz", - "integrity": "sha512-aS4yJuy6A1PCLws+PJpZP0qCURG8Y5iVx13z/WAbKyeDTY6W6PiGgcEllSaeLGxyn++382ztN/EZH85n2zZ6VQ==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.8.16.tgz", + "integrity": "sha512-NBgaqBDLQSZlJR4D5XCkQq6noaO0RvIgwm5eYFJYL3bH5dNu8o0UBpq7C5DYnQI8+ybyoHFjT5/icN4LeUYLow==", "cpu": [ "arm64" ], @@ -19978,9 +20039,9 @@ ] }, "node_modules/turbo-linux-64": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.8.14.tgz", - "integrity": "sha512-XC6wPUDJkakjhNLaS0NrHDMiujRVjH+naEAwvKLArgqRaFkNxjmyNDRM4eu3soMMFmjym6NTxYaF74rvET+Orw==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.8.16.tgz", + "integrity": "sha512-VYPdcCRevI9kR/hr1H1xwXy7QQt/jNKiim1e1mjANBXD2E9VZWMkIL74J1Huad5MbU3/jw7voHOqDPLJPC2p6w==", "cpu": [ "x64" ], @@ -19992,9 +20053,9 @@ ] }, "node_modules/turbo-linux-arm64": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.8.14.tgz", - "integrity": "sha512-ChfE7isyVNjZrVSPDwcfqcHLG/FuIBbOFxnt1FM8vSuBGzHAs8AlTdwFNIxlEMJfZ8Ad9mdMxdmsCUPIWiQ6cg==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.8.16.tgz", + "integrity": "sha512-beq8tgUVI3uwkQkXJMiOr/hfxQRw54M3elpBwqgYFfemiK5LhCjjcwO0DkE8GZZfElBIlk+saMAQOZy3885wNQ==", "cpu": [ "arm64" ], @@ -20006,9 +20067,9 @@ ] }, "node_modules/turbo-windows-64": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.8.14.tgz", - "integrity": "sha512-FTbIeQL1ycLFW2t9uQNMy+bRSzi3Xhwun/e7ZhFBdM+U0VZxxrtfYEBM9CHOejlfqomk6Jh7aRz0sJoqYn39Hg==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.8.16.tgz", + "integrity": "sha512-Ig7b46iUgiOIkea/D3Z7H+zNzvzSnIJcLYFpZLA0RxbUTrbLhv9qIPwv3pT9p/abmu0LXVKHxaOo+p26SuDhzw==", "cpu": [ "x64" ], @@ -20020,9 +20081,9 @@ ] }, "node_modules/turbo-windows-arm64": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.8.14.tgz", - "integrity": "sha512-KgZX12cTyhY030qS7ieT8zRkhZZE2VWJasDFVUSVVn17nR7IShpv68/7j5UqJNeRLIGF1XPK0phsP5V5yw3how==", + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.8.16.tgz", + "integrity": "sha512-fOWjbEA2PiE2HEnFQrwNZKYEdjewyPc2no9GmrXklZnTCuMsxeCN39aVlKpKpim03Zq/ykIuvApGwq8ZbfS2Yw==", "cpu": [ "arm64" ], @@ -20162,16 +20223,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.1.tgz", - "integrity": "sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.57.0.tgz", + "integrity": "sha512-W8GcigEMEeB07xEZol8oJ26rigm3+bfPHxHvwbYUlu1fUDsGuQ7Hiskx5xGW/xM4USc9Ephe3jtv7ZYPQntHeA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.56.1", - "@typescript-eslint/parser": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/utils": "8.56.1" + "@typescript-eslint/eslint-plugin": "8.57.0", + "@typescript-eslint/parser": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0", + "@typescript-eslint/utils": "8.57.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/packages/lib/src/HalstackContext.tsx b/packages/lib/src/HalstackContext.tsx index d37cfa2b82..cecbe49d4b 100644 --- a/packages/lib/src/HalstackContext.tsx +++ b/packages/lib/src/HalstackContext.tsx @@ -2,7 +2,7 @@ import { createContext, ReactNode, useMemo } from "react"; import styled from "@emotion/styled"; import { css } from "@emotion/react"; import { coreTokens, aliasTokens } from "./styles/tokens"; -import { ThemedLogos, TranslatedLabels, defaultTranslatedComponentLabels } from "./common/variables"; +import { defaultThemedLogos, TranslatedLabels, defaultTranslatedComponentLabels } from "./common/variables"; /** * This type is used to allow labels objects to be passed to the HalstackProvider. @@ -12,7 +12,7 @@ export type DeepPartial = { [P in keyof T]?: Partial; }; const HalstackLanguageContext = createContext(defaultTranslatedComponentLabels); -const HalstackLogosContext = createContext>(ThemedLogos); +const HalstackLogosContext = createContext>(defaultThemedLogos); const parseLabels = (labels: DeepPartial): TranslatedLabels => { const parsedLabels = defaultTranslatedComponentLabels; @@ -78,7 +78,7 @@ const HalstackProvider = ({ labels, children, opinionatedTheme }: HalstackProvid return ( - + {parsedLabels ? ( {children} ) : ( diff --git a/packages/lib/src/common/variables.ts b/packages/lib/src/common/variables.ts index 4fb7350161..b16adc089d 100644 --- a/packages/lib/src/common/variables.ts +++ b/packages/lib/src/common/variables.ts @@ -133,7 +133,7 @@ export const defaultTranslatedComponentLabels = { export type TranslatedLabels = typeof defaultTranslatedComponentLabels; -export const ThemedLogos = { +export const defaultThemedLogos = { mainLogo: undefined, footerLogo: undefined, footerReducedLogo: undefined, diff --git a/packages/lib/src/popover/types.ts b/packages/lib/src/popover/types.ts index c4809a54cb..db91a076b1 100644 --- a/packages/lib/src/popover/types.ts +++ b/packages/lib/src/popover/types.ts @@ -1,5 +1,3 @@ -import React from "react"; - export type PopoverPropsType = { /** Action that triggers the popover to open. */ actionToOpen?: "click" | "hover"; diff --git a/packages/lib/src/select/Select.tsx b/packages/lib/src/select/Select.tsx index 036cab2670..07b982e4db 100644 --- a/packages/lib/src/select/Select.tsx +++ b/packages/lib/src/select/Select.tsx @@ -255,7 +255,7 @@ const DxcSelect = forwardRef( }; const handleOnChangeValue = useCallback( - (newOption?: ListOptionType) => { + (newOption?: ListOptionType | ListOptionType[]) => { if (newOption) { if (multiple) { if (value == null) { @@ -281,13 +281,15 @@ const DxcSelect = forwardRef( }); } } else { - if (value == null) setInnerValue(newOption.value); - onChange?.({ - value: newOption.value as string & string[], - error: notOptionalCheck(newOption.value, multiple, optional) - ? translatedLabels.formFields.requiredValueErrorMessage - : undefined, - }); + if (!Array.isArray(newOption)) { + if (value == null) setInnerValue(newOption.value); + onChange?.({ + value: newOption.value as string & string[], + error: notOptionalCheck(newOption.value, multiple, optional) + ? translatedLabels.formFields.requiredValueErrorMessage + : undefined, + }); + } } } }, @@ -458,7 +460,7 @@ const DxcSelect = forwardRef( }; const handleOptionOnClick = useCallback( - (option: ListOptionType) => { + (option: ListOptionType | ListOptionType[]) => { handleOnChangeValue(option); if (!multiple) closeListbox(); setSearchValue(""); @@ -477,11 +479,11 @@ const DxcSelect = forwardRef( const handleSelectAllGroup = useCallback( (group: ListOptionGroupType) => { const groupSelectionType = getGroupSelectionType(group.options, (value ?? innerValue) as string[]); - if (groupSelectionType === "indeterminate") - group.options.forEach( - (option) => !(value ?? innerValue).includes(option.value) && handleOptionOnClick(option) - ); - else group.options.forEach((option) => handleOptionOnClick(option)); + handleOptionOnClick( + groupSelectionType === "indeterminate" + ? group.options.filter((option) => !(value ?? innerValue).includes(option.value)) + : group.options + ); }, [handleOptionOnClick, innerValue, value] ); diff --git a/packages/lib/src/select/utils.ts b/packages/lib/src/select/utils.ts index 1720aa34eb..215c1b0d15 100644 --- a/packages/lib/src/select/utils.ts +++ b/packages/lib/src/select/utils.ts @@ -224,12 +224,22 @@ export const getSelectableOptionsValues = (options: Props["options"]) => : options.map((option) => option.value); /** - * (Un)Selects the option passed as parameter. - * @param currentValue - * @param newOption - * @returns + * (Un)Selects one or multiple options passed as parameter. + * @param currentValue Current selected values + * @param newOptions Option or array of options to toggle + * @returns Updated array of values */ -export const computeNewValue = (currentValue: string[], newOption: ListOptionType) => - currentValue.includes(newOption.value) - ? currentValue.filter((val) => val !== newOption.value) - : [...currentValue, newOption.value]; +export const computeNewValue = (currentValue: string[], newOptions: ListOptionType | ListOptionType[]) => { + const optionsArray = Array.isArray(newOptions) ? newOptions : [newOptions]; + let updatedValue = [...currentValue]; + + optionsArray.forEach((option) => { + if (updatedValue.includes(option.value)) { + updatedValue = updatedValue.filter((val) => val !== option.value); + } else { + updatedValue.push(option.value); + } + }); + + return updatedValue; +}; diff --git a/packages/lib/src/tooltip/Tooltip.stories.tsx b/packages/lib/src/tooltip/Tooltip.stories.tsx index cc2ea49a84..05e7a78162 100644 --- a/packages/lib/src/tooltip/Tooltip.stories.tsx +++ b/packages/lib/src/tooltip/Tooltip.stories.tsx @@ -6,6 +6,7 @@ import DxcButton from "../button/Button"; import DxcFlex from "../flex/Flex"; import DxcInset from "../inset/Inset"; import { userEvent, within } from "storybook/internal/test"; +import styled from "@emotion/styled"; export default { title: "Tooltip", @@ -75,6 +76,19 @@ const RightTooltip = () => ( ); +const FullWidthTooltip = () => ( + <> + + <ExampleContainer> + <FullWidthContainer> + <DxcTooltip label="Tooltip Test"> + <DxcButton label="Hoverable button" /> + </DxcTooltip> + </FullWidthContainer> + </ExampleContainer> + </> +); + type Story = StoryObj<typeof DxcTooltip>; export const Chromatic: Story = { @@ -121,3 +135,18 @@ export const TooltipPositionRight: Story = { await userEvent.hover(button); }, }; + +export const TooltipFullWidth: Story = { + render: FullWidthTooltip, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const button = await canvas.findByRole("button"); + await userEvent.hover(button); + }, +}; + +const FullWidthContainer = styled.div` + width: 100%; + flex-direction: column; + display: flex; +`; diff --git a/packages/lib/src/tooltip/Tooltip.tsx b/packages/lib/src/tooltip/Tooltip.tsx index f5a11b3d0b..6e3b4e384c 100644 --- a/packages/lib/src/tooltip/Tooltip.tsx +++ b/packages/lib/src/tooltip/Tooltip.tsx @@ -7,6 +7,7 @@ import TooltipContext from "./TooltipContext"; const TooltipTriggerContainer = styled.div` position: relative; display: inline-flex; + width: fit-content; `; const StyledTooltipContent = styled(Content)`