diff --git a/.changeset/brown-mails-clap.md b/.changeset/brown-mails-clap.md new file mode 100644 index 00000000..9cafae1d --- /dev/null +++ b/.changeset/brown-mails-clap.md @@ -0,0 +1,6 @@ +--- +"reshaped": patch +"@reshaped/utilities": patch +--- + +classNames: moved to @reshaped/utilities and re-exported from reshaped diff --git a/packages/reshaped/src/components/Accordion/AccordionControlled.tsx b/packages/reshaped/src/components/Accordion/AccordionControlled.tsx index d234d853..64c948aa 100644 --- a/packages/reshaped/src/components/Accordion/AccordionControlled.tsx +++ b/packages/reshaped/src/components/Accordion/AccordionControlled.tsx @@ -4,7 +4,7 @@ import React from "react"; import useElementId from "hooks/useElementId"; import useHandlerRef from "hooks/useHandlerRef"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import AccordionContext from "./Accordion.context"; import * as T from "./Accordion.types"; diff --git a/packages/reshaped/src/components/Accordion/AccordionTrigger.tsx b/packages/reshaped/src/components/Accordion/AccordionTrigger.tsx index 6964e445..9323c9e3 100644 --- a/packages/reshaped/src/components/Accordion/AccordionTrigger.tsx +++ b/packages/reshaped/src/components/Accordion/AccordionTrigger.tsx @@ -6,7 +6,7 @@ import Actionable from "components/Actionable"; import Icon from "components/Icon"; import View from "components/View"; import IconChevronDown from "icons/ChevronDown"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import AccordionContext from "./Accordion.context"; import s from "./Accordion.module.css"; diff --git a/packages/reshaped/src/components/ActionBar/ActionBar.tsx b/packages/reshaped/src/components/ActionBar/ActionBar.tsx index cde3b028..7b2fddd9 100644 --- a/packages/reshaped/src/components/ActionBar/ActionBar.tsx +++ b/packages/reshaped/src/components/ActionBar/ActionBar.tsx @@ -1,5 +1,7 @@ +import { classNames } from "@reshaped/utilities"; + import View from "components/View"; -import { classNames, responsiveVariables } from "utilities/props"; +import { responsiveVariables } from "utilities/props"; import s from "./ActionBar.module.css"; diff --git a/packages/reshaped/src/components/Avatar/Avatar.tsx b/packages/reshaped/src/components/Avatar/Avatar.tsx index 7098d017..d1f0b43c 100644 --- a/packages/reshaped/src/components/Avatar/Avatar.tsx +++ b/packages/reshaped/src/components/Avatar/Avatar.tsx @@ -1,8 +1,10 @@ +import { classNames } from "@reshaped/utilities"; + import Icon from "components/Icon"; import Image, { type ImageProps } from "components/Image"; import View from "components/View"; import { resolveMixin } from "styles/mixin"; -import { classNames, responsivePropDependency } from "utilities/props"; +import { responsivePropDependency } from "utilities/props"; import s from "./Avatar.module.css"; diff --git a/packages/reshaped/src/components/Badge/Badge.tsx b/packages/reshaped/src/components/Badge/Badge.tsx index d0113502..cccf0eb7 100644 --- a/packages/reshaped/src/components/Badge/Badge.tsx +++ b/packages/reshaped/src/components/Badge/Badge.tsx @@ -4,7 +4,7 @@ import Actionable, { type ActionableProps, type ActionableRef } from "components import Icon from "components/Icon"; import Text from "components/Text"; import IconClose from "icons/Close"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Badge.module.css"; diff --git a/packages/reshaped/src/components/Badge/BadgeContainer.tsx b/packages/reshaped/src/components/Badge/BadgeContainer.tsx index d6d21d4c..87493b88 100644 --- a/packages/reshaped/src/components/Badge/BadgeContainer.tsx +++ b/packages/reshaped/src/components/Badge/BadgeContainer.tsx @@ -1,4 +1,4 @@ -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Badge.module.css"; diff --git a/packages/reshaped/src/components/Breadcrumbs/Breadcrumbs.tsx b/packages/reshaped/src/components/Breadcrumbs/Breadcrumbs.tsx index 6b0b8614..67fa91cb 100644 --- a/packages/reshaped/src/components/Breadcrumbs/Breadcrumbs.tsx +++ b/packages/reshaped/src/components/Breadcrumbs/Breadcrumbs.tsx @@ -8,7 +8,7 @@ import Text from "components/Text"; import View from "components/View"; import IconChevronRight from "icons/ChevronRight"; import IconDotsHorizontal from "icons/DotsHorizontal"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import * as T from "./Breadcrumbs.types"; diff --git a/packages/reshaped/src/components/Button/Button.tsx b/packages/reshaped/src/components/Button/Button.tsx index 15c93174..d0877176 100644 --- a/packages/reshaped/src/components/Button/Button.tsx +++ b/packages/reshaped/src/components/Button/Button.tsx @@ -1,9 +1,10 @@ +import { classNames } from "@reshaped/utilities"; import { forwardRef } from "react"; import Actionable, { type ActionableRef } from "components/Actionable"; import Icon from "components/Icon"; import Loader from "components/Loader"; -import { classNames, responsiveClassNames, responsivePropDependency } from "utilities/props"; +import { responsiveClassNames, responsivePropDependency } from "utilities/props"; import s from "./Button.module.css"; diff --git a/packages/reshaped/src/components/Button/ButtonGroup.tsx b/packages/reshaped/src/components/Button/ButtonGroup.tsx index 3553bacf..8714bac6 100644 --- a/packages/reshaped/src/components/Button/ButtonGroup.tsx +++ b/packages/reshaped/src/components/Button/ButtonGroup.tsx @@ -1,4 +1,4 @@ -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Button.module.css"; diff --git a/packages/reshaped/src/components/Calendar/CalendarDate.tsx b/packages/reshaped/src/components/Calendar/CalendarDate.tsx index 61c3687a..829aebbe 100644 --- a/packages/reshaped/src/components/Calendar/CalendarDate.tsx +++ b/packages/reshaped/src/components/Calendar/CalendarDate.tsx @@ -1,7 +1,7 @@ "use client"; import Actionable from "components/Actionable"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Calendar.module.css"; import { getLocalISODate } from "./Calendar.utils"; diff --git a/packages/reshaped/src/components/Card/Card.tsx b/packages/reshaped/src/components/Card/Card.tsx index 94b57fc8..cf2d6637 100644 --- a/packages/reshaped/src/components/Card/Card.tsx +++ b/packages/reshaped/src/components/Card/Card.tsx @@ -2,7 +2,7 @@ import React, { forwardRef } from "react"; import Actionable from "components/Actionable"; import { resolveMixin } from "styles/mixin"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Card.module.css"; diff --git a/packages/reshaped/src/components/Carousel/Carousel.tsx b/packages/reshaped/src/components/Carousel/Carousel.tsx index 3c5aa2a5..bea881d3 100644 --- a/packages/reshaped/src/components/Carousel/Carousel.tsx +++ b/packages/reshaped/src/components/Carousel/Carousel.tsx @@ -1,12 +1,13 @@ "use client"; +import { classNames } from "@reshaped/utilities"; import React from "react"; import View from "components/View"; import useIsomorphicLayoutEffect from "hooks/useIsomorphicLayoutEffect"; import useRTL from "hooks/useRTL"; import { rafThrottle } from "utilities/helpers"; -import { classNames, responsiveVariables, responsiveClassNames } from "utilities/props"; +import { responsiveVariables, responsiveClassNames } from "utilities/props"; import s from "./Carousel.module.css"; import * as T from "./Carousel.types"; diff --git a/packages/reshaped/src/components/Carousel/CarouselControl.tsx b/packages/reshaped/src/components/Carousel/CarouselControl.tsx index 7cc10172..e8d58fab 100644 --- a/packages/reshaped/src/components/Carousel/CarouselControl.tsx +++ b/packages/reshaped/src/components/Carousel/CarouselControl.tsx @@ -6,7 +6,7 @@ import Button from "components/Button"; import useIsomorphicLayoutEffect from "hooks/useIsomorphicLayoutEffect"; import IconChevronLeft from "icons/ChevronLeft"; import IconChevronRight from "icons/ChevronRight"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Carousel.module.css"; import * as T from "./Carousel.types"; diff --git a/packages/reshaped/src/components/Checkbox/Checkbox.tsx b/packages/reshaped/src/components/Checkbox/Checkbox.tsx index dd6a6fa9..45e394e0 100644 --- a/packages/reshaped/src/components/Checkbox/Checkbox.tsx +++ b/packages/reshaped/src/components/Checkbox/Checkbox.tsx @@ -1,5 +1,6 @@ "use client"; +import { classNames } from "@reshaped/utilities"; import React from "react"; import { useCheckboxGroup } from "components/CheckboxGroup"; @@ -9,7 +10,7 @@ import Icon from "components/Icon"; import Text from "components/Text"; import useIsomorphicLayoutEffect from "hooks/useIsomorphicLayoutEffect"; import IconCheckmark from "icons/Checkmark"; -import { classNames, responsiveClassNames, responsivePropDependency } from "utilities/props"; +import { responsiveClassNames, responsivePropDependency } from "utilities/props"; import s from "./Checkbox.module.css"; diff --git a/packages/reshaped/src/components/Container/Container.tsx b/packages/reshaped/src/components/Container/Container.tsx index b3243997..e9c8eb0e 100644 --- a/packages/reshaped/src/components/Container/Container.tsx +++ b/packages/reshaped/src/components/Container/Container.tsx @@ -1,5 +1,5 @@ import View from "components/View"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Container.module.css"; diff --git a/packages/reshaped/src/components/Dismissible/Dismissible.tsx b/packages/reshaped/src/components/Dismissible/Dismissible.tsx index 4c524e33..31fc4054 100644 --- a/packages/reshaped/src/components/Dismissible/Dismissible.tsx +++ b/packages/reshaped/src/components/Dismissible/Dismissible.tsx @@ -2,7 +2,7 @@ import Button from "components/Button"; import IconClose from "icons/Close"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Dismissible.module.css"; diff --git a/packages/reshaped/src/components/Divider/Divider.tsx b/packages/reshaped/src/components/Divider/Divider.tsx index a4eb82e6..01635ce0 100644 --- a/packages/reshaped/src/components/Divider/Divider.tsx +++ b/packages/reshaped/src/components/Divider/Divider.tsx @@ -1,5 +1,7 @@ +import { classNames } from "@reshaped/utilities"; + import Text from "components/Text"; -import { classNames, responsiveClassNames } from "utilities/props"; +import { responsiveClassNames } from "utilities/props"; import s from "./Divider.module.css"; diff --git a/packages/reshaped/src/components/DropdownMenu/DropdownMenu.tsx b/packages/reshaped/src/components/DropdownMenu/DropdownMenu.tsx index 9fb4e5ec..dab434db 100644 --- a/packages/reshaped/src/components/DropdownMenu/DropdownMenu.tsx +++ b/packages/reshaped/src/components/DropdownMenu/DropdownMenu.tsx @@ -10,7 +10,7 @@ import * as keys from "constants/keys"; import useHotkeys from "hooks/useHotkeys"; import useRTL from "hooks/useRTL"; import IconChevronRight from "icons/ChevronRight"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./DropdownMenu.module.css"; diff --git a/packages/reshaped/src/components/FileUpload/FileUpload.tsx b/packages/reshaped/src/components/FileUpload/FileUpload.tsx index 584502ff..7e6e677f 100644 --- a/packages/reshaped/src/components/FileUpload/FileUpload.tsx +++ b/packages/reshaped/src/components/FileUpload/FileUpload.tsx @@ -5,7 +5,7 @@ import React from "react"; import HiddenVisually from "components/HiddenVisually"; import View from "components/View"; import useToggle from "hooks/useToggle"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./FileUpload.module.css"; diff --git a/packages/reshaped/src/components/Flyout/FlyoutContent.tsx b/packages/reshaped/src/components/Flyout/FlyoutContent.tsx index 8d5b0edf..cc694b77 100644 --- a/packages/reshaped/src/components/Flyout/FlyoutContent.tsx +++ b/packages/reshaped/src/components/Flyout/FlyoutContent.tsx @@ -4,7 +4,7 @@ import React from "react"; import Portal from "components/_private/Portal"; import useIsomorphicLayoutEffect from "hooks/useIsomorphicLayoutEffect"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import { useFlyoutContext, ContentProvider } from "./Flyout.context"; import s from "./Flyout.module.css"; diff --git a/packages/reshaped/src/components/Grid/Grid.tsx b/packages/reshaped/src/components/Grid/Grid.tsx index 3f85714c..be176589 100644 --- a/packages/reshaped/src/components/Grid/Grid.tsx +++ b/packages/reshaped/src/components/Grid/Grid.tsx @@ -1,5 +1,7 @@ +import { classNames } from "@reshaped/utilities"; + import { resolveMixin } from "styles/mixin"; -import { classNames, responsiveVariables, responsivePropDependency } from "utilities/props"; +import { responsiveVariables, responsivePropDependency } from "utilities/props"; import s from "./Grid.module.css"; diff --git a/packages/reshaped/src/components/Hidden/Hidden.tsx b/packages/reshaped/src/components/Hidden/Hidden.tsx index d3eb4740..c17abb03 100644 --- a/packages/reshaped/src/components/Hidden/Hidden.tsx +++ b/packages/reshaped/src/components/Hidden/Hidden.tsx @@ -1,4 +1,6 @@ -import { classNames, responsiveClassNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; + +import { responsiveClassNames } from "utilities/props"; import s from "./Hidden.module.css"; diff --git a/packages/reshaped/src/components/HiddenInput/HiddenInput.tsx b/packages/reshaped/src/components/HiddenInput/HiddenInput.tsx index a1d22ef1..ffc8307c 100644 --- a/packages/reshaped/src/components/HiddenInput/HiddenInput.tsx +++ b/packages/reshaped/src/components/HiddenInput/HiddenInput.tsx @@ -1,7 +1,7 @@ import { useCheckboxGroup } from "components/CheckboxGroup"; import { useFormControl } from "components/FormControl"; import { useRadioGroup } from "components/RadioGroup"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./HiddenInput.module.css"; diff --git a/packages/reshaped/src/components/Hotkey/Hotkey.tsx b/packages/reshaped/src/components/Hotkey/Hotkey.tsx index 83887f49..666fdcd0 100644 --- a/packages/reshaped/src/components/Hotkey/Hotkey.tsx +++ b/packages/reshaped/src/components/Hotkey/Hotkey.tsx @@ -1,5 +1,5 @@ import Text from "components/Text"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Hotkey.module.css"; diff --git a/packages/reshaped/src/components/Icon/Icon.tsx b/packages/reshaped/src/components/Icon/Icon.tsx index 992d85b4..0f97c515 100644 --- a/packages/reshaped/src/components/Icon/Icon.tsx +++ b/packages/reshaped/src/components/Icon/Icon.tsx @@ -1,7 +1,7 @@ import React from "react"; import { resolveMixin } from "styles/mixin"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Icon.module.css"; diff --git a/packages/reshaped/src/components/Image/Image.tsx b/packages/reshaped/src/components/Image/Image.tsx index aabfc800..fcbbfc85 100644 --- a/packages/reshaped/src/components/Image/Image.tsx +++ b/packages/reshaped/src/components/Image/Image.tsx @@ -3,7 +3,7 @@ import React from "react"; import { resolveMixin } from "styles/mixin"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Image.module.css"; import * as T from "./Image.types"; diff --git a/packages/reshaped/src/components/Link/Link.tsx b/packages/reshaped/src/components/Link/Link.tsx index b38f50b2..c5119bb5 100644 --- a/packages/reshaped/src/components/Link/Link.tsx +++ b/packages/reshaped/src/components/Link/Link.tsx @@ -2,7 +2,7 @@ import { forwardRef } from "react"; import Actionable, { type ActionableRef } from "components/Actionable"; import Icon from "components/Icon"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Link.module.css"; diff --git a/packages/reshaped/src/components/Loader/Loader.tsx b/packages/reshaped/src/components/Loader/Loader.tsx index 2e1b3ce2..ca8bc07b 100644 --- a/packages/reshaped/src/components/Loader/Loader.tsx +++ b/packages/reshaped/src/components/Loader/Loader.tsx @@ -1,4 +1,6 @@ -import { classNames, responsiveClassNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; + +import { responsiveClassNames } from "utilities/props"; import s from "./Loader.module.css"; diff --git a/packages/reshaped/src/components/MenuItem/MenuItem.tsx b/packages/reshaped/src/components/MenuItem/MenuItem.tsx index df7303bf..54751f3a 100644 --- a/packages/reshaped/src/components/MenuItem/MenuItem.tsx +++ b/packages/reshaped/src/components/MenuItem/MenuItem.tsx @@ -1,9 +1,10 @@ +import { classNames } from "@reshaped/utilities"; import { forwardRef } from "react"; import Actionable, { type ActionableRef } from "components/Actionable"; import Icon from "components/Icon"; import View from "components/View"; -import { classNames, responsiveClassNames, responsivePropDependency } from "utilities/props"; +import { responsiveClassNames, responsivePropDependency } from "utilities/props"; import s from "./MenuItem.module.css"; diff --git a/packages/reshaped/src/components/Modal/Modal.tsx b/packages/reshaped/src/components/Modal/Modal.tsx index 492824d3..c1ed664a 100644 --- a/packages/reshaped/src/components/Modal/Modal.tsx +++ b/packages/reshaped/src/components/Modal/Modal.tsx @@ -1,5 +1,6 @@ "use client"; +import { classNames } from "@reshaped/utilities"; import React from "react"; import Overlay from "components/Overlay"; @@ -8,7 +9,7 @@ import useElementId from "hooks/useElementId"; import useHandlerRef from "hooks/useHandlerRef"; import useResponsiveClientValue from "hooks/useResponsiveClientValue"; import { resolveMixin } from "styles/mixin"; -import { classNames, responsiveVariables, responsiveClassNames } from "utilities/props"; +import { responsiveVariables, responsiveClassNames } from "utilities/props"; import { enableScroll, disableScroll } from "utilities/scroll"; import s from "./Modal.module.css"; diff --git a/packages/reshaped/src/components/Overlay/Overlay.tsx b/packages/reshaped/src/components/Overlay/Overlay.tsx index ad9b8338..740fb324 100644 --- a/packages/reshaped/src/components/Overlay/Overlay.tsx +++ b/packages/reshaped/src/components/Overlay/Overlay.tsx @@ -12,7 +12,7 @@ import useIsomorphicLayoutEffect from "hooks/useIsomorphicLayoutEffect"; import useScrollLock from "hooks/useScrollLock"; import useToggle from "hooks/useToggle"; import { onNextFrame } from "utilities/animation"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Overlay.module.css"; diff --git a/packages/reshaped/src/components/Popover/Popover.tsx b/packages/reshaped/src/components/Popover/Popover.tsx index 1917df11..6feef39c 100644 --- a/packages/reshaped/src/components/Popover/Popover.tsx +++ b/packages/reshaped/src/components/Popover/Popover.tsx @@ -1,7 +1,7 @@ import Dismissible, { type DismissibleProps } from "components/Dismissible"; import Flyout, { useFlyoutContext, type FlyoutProps } from "components/Flyout"; import { resolveMixin } from "styles/mixin"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Popover.module.css"; diff --git a/packages/reshaped/src/components/Progress/Progress.tsx b/packages/reshaped/src/components/Progress/Progress.tsx index 226edba7..126d4714 100644 --- a/packages/reshaped/src/components/Progress/Progress.tsx +++ b/packages/reshaped/src/components/Progress/Progress.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Progress.module.css"; diff --git a/packages/reshaped/src/components/ProgressIndicator/ProgressIndicator.tsx b/packages/reshaped/src/components/ProgressIndicator/ProgressIndicator.tsx index ab59d558..575c7d4d 100644 --- a/packages/reshaped/src/components/ProgressIndicator/ProgressIndicator.tsx +++ b/packages/reshaped/src/components/ProgressIndicator/ProgressIndicator.tsx @@ -2,7 +2,7 @@ import React from "react"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./ProgressIndicator.module.css"; diff --git a/packages/reshaped/src/components/Radio/Radio.tsx b/packages/reshaped/src/components/Radio/Radio.tsx index 76b378d8..444ab015 100644 --- a/packages/reshaped/src/components/Radio/Radio.tsx +++ b/packages/reshaped/src/components/Radio/Radio.tsx @@ -1,12 +1,13 @@ "use client"; +import { classNames } from "@reshaped/utilities"; import React from "react"; import { useFormControl } from "components/FormControl"; import HiddenInput from "components/HiddenInput"; import { useRadioGroup } from "components/RadioGroup"; import Text from "components/Text"; -import { classNames, responsiveClassNames, responsivePropDependency } from "utilities/props"; +import { responsiveClassNames, responsivePropDependency } from "utilities/props"; import s from "./Radio.module.css"; diff --git a/packages/reshaped/src/components/Reshaped/Reshaped.tsx b/packages/reshaped/src/components/Reshaped/Reshaped.tsx index 580ce3e4..cccd6493 100644 --- a/packages/reshaped/src/components/Reshaped/Reshaped.tsx +++ b/packages/reshaped/src/components/Reshaped/Reshaped.tsx @@ -11,7 +11,7 @@ import { } from "hooks/_private/useSingletonEnvironment"; import { SingletonHotkeysProvider } from "hooks/_private/useSingletonHotkeys"; import { SingletonKeyboardModeProvider } from "hooks/_private/useSingletonKeyboardMode"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Reshaped.module.css"; diff --git a/packages/reshaped/src/components/Resizable/Resizable.tsx b/packages/reshaped/src/components/Resizable/Resizable.tsx index 9155e7f0..80677f3c 100644 --- a/packages/reshaped/src/components/Resizable/Resizable.tsx +++ b/packages/reshaped/src/components/Resizable/Resizable.tsx @@ -3,7 +3,7 @@ import React from "react"; import View from "components/View"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Resizable.module.css"; import { ResizableHandleContext } from "./ResizableHandle"; diff --git a/packages/reshaped/src/components/Resizable/ResizableHandle.tsx b/packages/reshaped/src/components/Resizable/ResizableHandle.tsx index 804df437..8ab4f51d 100644 --- a/packages/reshaped/src/components/Resizable/ResizableHandle.tsx +++ b/packages/reshaped/src/components/Resizable/ResizableHandle.tsx @@ -4,7 +4,7 @@ import React from "react"; import View from "components/View"; import useDrag from "hooks/_private/useDrag"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Resizable.module.css"; diff --git a/packages/reshaped/src/components/Scrim/Scrim.tsx b/packages/reshaped/src/components/Scrim/Scrim.tsx index d6b60eb3..868c7ee2 100644 --- a/packages/reshaped/src/components/Scrim/Scrim.tsx +++ b/packages/reshaped/src/components/Scrim/Scrim.tsx @@ -1,5 +1,5 @@ import View from "components/View"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Scrim.module.css"; diff --git a/packages/reshaped/src/components/ScrollArea/ScrollArea.tsx b/packages/reshaped/src/components/ScrollArea/ScrollArea.tsx index 643169b5..6e6d40b6 100644 --- a/packages/reshaped/src/components/ScrollArea/ScrollArea.tsx +++ b/packages/reshaped/src/components/ScrollArea/ScrollArea.tsx @@ -5,7 +5,7 @@ import React, { forwardRef } from "react"; import useHandlerRef from "hooks/useHandlerRef"; import useIsomorphicLayoutEffect from "hooks/useIsomorphicLayoutEffect"; import { resolveMixin } from "styles/mixin"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import { disableScroll, enableScroll } from "utilities/scroll"; import s from "./ScrollArea.module.css"; diff --git a/packages/reshaped/src/components/Select/SelectNative.tsx b/packages/reshaped/src/components/Select/SelectNative.tsx index b735deb1..0e254339 100644 --- a/packages/reshaped/src/components/Select/SelectNative.tsx +++ b/packages/reshaped/src/components/Select/SelectNative.tsx @@ -2,7 +2,7 @@ import React from "react"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Select.module.css"; import SelectEndContent from "./SelectEndContent"; diff --git a/packages/reshaped/src/components/Select/SelectRoot.tsx b/packages/reshaped/src/components/Select/SelectRoot.tsx index 7559e5aa..ef8dc4e9 100644 --- a/packages/reshaped/src/components/Select/SelectRoot.tsx +++ b/packages/reshaped/src/components/Select/SelectRoot.tsx @@ -1,10 +1,11 @@ "use client"; +import { classNames } from "@reshaped/utilities"; import React from "react"; import { useFormControl } from "components/FormControl"; import useElementId from "hooks/useElementId"; -import { classNames, responsiveClassNames } from "utilities/props"; +import { responsiveClassNames } from "utilities/props"; import s from "./Select.module.css"; diff --git a/packages/reshaped/src/components/Skeleton/Skeleton.tsx b/packages/reshaped/src/components/Skeleton/Skeleton.tsx index 39baf15f..62bfedc6 100644 --- a/packages/reshaped/src/components/Skeleton/Skeleton.tsx +++ b/packages/reshaped/src/components/Skeleton/Skeleton.tsx @@ -1,5 +1,5 @@ import View from "components/View"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Skeleton.module.css"; import * as T from "./Skeleton.types"; diff --git a/packages/reshaped/src/components/Slider/SliderControlled.tsx b/packages/reshaped/src/components/Slider/SliderControlled.tsx index 48a0d301..c3b6488f 100644 --- a/packages/reshaped/src/components/Slider/SliderControlled.tsx +++ b/packages/reshaped/src/components/Slider/SliderControlled.tsx @@ -7,7 +7,7 @@ import useElementId from "hooks/useElementId"; import useHandlerRef from "hooks/useHandlerRef"; import useRTL from "hooks/useRTL"; import { triggerChangeEvent } from "utilities/dom"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import { disableScroll, enableScroll } from "utilities/scroll"; import s from "./Slider.module.css"; diff --git a/packages/reshaped/src/components/Slider/SliderThumb.tsx b/packages/reshaped/src/components/Slider/SliderThumb.tsx index efa49639..6b30cad9 100644 --- a/packages/reshaped/src/components/Slider/SliderThumb.tsx +++ b/packages/reshaped/src/components/Slider/SliderThumb.tsx @@ -4,7 +4,7 @@ import React from "react"; import Text from "components/Text"; import Theme from "components/Theme"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Slider.module.css"; import { getPrecision } from "./Slider.utilities"; diff --git a/packages/reshaped/src/components/Switch/Switch.tsx b/packages/reshaped/src/components/Switch/Switch.tsx index 09d48b7a..1b40edde 100644 --- a/packages/reshaped/src/components/Switch/Switch.tsx +++ b/packages/reshaped/src/components/Switch/Switch.tsx @@ -1,11 +1,12 @@ "use client"; +import { classNames } from "@reshaped/utilities"; import React from "react"; import { useFormControl } from "components/FormControl"; import Text from "components/Text"; import useElementId from "hooks/useElementId"; -import { classNames, responsiveClassNames, responsivePropDependency } from "utilities/props"; +import { responsiveClassNames, responsivePropDependency } from "utilities/props"; import s from "./Switch.module.css"; diff --git a/packages/reshaped/src/components/Table/Table.tsx b/packages/reshaped/src/components/Table/Table.tsx index c9abc31a..f7be215e 100644 --- a/packages/reshaped/src/components/Table/Table.tsx +++ b/packages/reshaped/src/components/Table/Table.tsx @@ -1,10 +1,11 @@ "use client"; +import { classNames } from "@reshaped/utilities"; import React, { isValidElement } from "react"; import useFadeSide from "hooks/_private/useFadeSide"; import { resolveMixin } from "styles/mixin"; -import { classNames, responsiveVariables } from "utilities/props"; +import { responsiveVariables } from "utilities/props"; import s from "./Table.module.css"; diff --git a/packages/reshaped/src/components/Tabs/TabsItem.tsx b/packages/reshaped/src/components/Tabs/TabsItem.tsx index 6a63f966..71d08633 100644 --- a/packages/reshaped/src/components/Tabs/TabsItem.tsx +++ b/packages/reshaped/src/components/Tabs/TabsItem.tsx @@ -8,7 +8,7 @@ import Icon from "components/Icon"; import Text from "components/Text"; import useIsomorphicLayoutEffect from "hooks/useIsomorphicLayoutEffect"; import { findParent } from "utilities/dom"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Tabs.module.css"; import { useTabs } from "./TabsContext"; diff --git a/packages/reshaped/src/components/Tabs/TabsList.tsx b/packages/reshaped/src/components/Tabs/TabsList.tsx index a6950b75..c3d087cb 100644 --- a/packages/reshaped/src/components/Tabs/TabsList.tsx +++ b/packages/reshaped/src/components/Tabs/TabsList.tsx @@ -10,7 +10,7 @@ import useKeyboardArrowNavigation from "hooks/useKeyboardArrowNavigation"; import useRTL from "hooks/useRTL"; import IconChevronLeft from "icons/ChevronLeft"; import IconChevronRight from "icons/ChevronRight"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Tabs.module.css"; import { useTabs } from "./TabsContext"; diff --git a/packages/reshaped/src/components/Tabs/TabsPanel.tsx b/packages/reshaped/src/components/Tabs/TabsPanel.tsx index c1b29979..93803d58 100644 --- a/packages/reshaped/src/components/Tabs/TabsPanel.tsx +++ b/packages/reshaped/src/components/Tabs/TabsPanel.tsx @@ -3,7 +3,7 @@ import { getFocusableElements } from "@reshaped/utilities/internal"; import React from "react"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Tabs.module.css"; import { useTabs } from "./TabsContext"; diff --git a/packages/reshaped/src/components/Text/Text.tsx b/packages/reshaped/src/components/Text/Text.tsx index 03ae8c5a..ed425499 100644 --- a/packages/reshaped/src/components/Text/Text.tsx +++ b/packages/reshaped/src/components/Text/Text.tsx @@ -1,5 +1,7 @@ +import { classNames } from "@reshaped/utilities"; + import { resolveMixin } from "styles/mixin"; -import { classNames, responsiveClassNames } from "utilities/props"; +import { responsiveClassNames } from "utilities/props"; import s from "./Text.module.css"; diff --git a/packages/reshaped/src/components/TextArea/TextArea.tsx b/packages/reshaped/src/components/TextArea/TextArea.tsx index fb6266cf..77a35165 100644 --- a/packages/reshaped/src/components/TextArea/TextArea.tsx +++ b/packages/reshaped/src/components/TextArea/TextArea.tsx @@ -1,10 +1,11 @@ "use client"; +import { classNames } from "@reshaped/utilities"; import React from "react"; import { useFormControl } from "components/FormControl"; import useElementId from "hooks/useElementId"; -import { classNames, responsiveClassNames } from "utilities/props"; +import { responsiveClassNames } from "utilities/props"; import s from "./TextArea.module.css"; diff --git a/packages/reshaped/src/components/TextField/TextField.tsx b/packages/reshaped/src/components/TextField/TextField.tsx index bfd1aa20..543053d6 100644 --- a/packages/reshaped/src/components/TextField/TextField.tsx +++ b/packages/reshaped/src/components/TextField/TextField.tsx @@ -1,11 +1,12 @@ "use client"; +import { classNames } from "@reshaped/utilities"; import React from "react"; import { useFormControl } from "components/FormControl"; import Icon from "components/Icon"; import useElementId from "hooks/useElementId"; -import { classNames, responsiveClassNames, responsivePropDependency } from "utilities/props"; +import { responsiveClassNames, responsivePropDependency } from "utilities/props"; import s from "./TextField.module.css"; diff --git a/packages/reshaped/src/components/Theme/Theme.tsx b/packages/reshaped/src/components/Theme/Theme.tsx index 3b541a0e..936cc32f 100644 --- a/packages/reshaped/src/components/Theme/Theme.tsx +++ b/packages/reshaped/src/components/Theme/Theme.tsx @@ -3,7 +3,7 @@ import React from "react"; import useIsomorphicLayoutEffect from "hooks/useIsomorphicLayoutEffect"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import { ThemeContext } from "./Theme.context"; import s from "./Theme.module.css"; diff --git a/packages/reshaped/src/components/Timeline/Timeline.tsx b/packages/reshaped/src/components/Timeline/Timeline.tsx index fd4ed688..99fcf2d6 100644 --- a/packages/reshaped/src/components/Timeline/Timeline.tsx +++ b/packages/reshaped/src/components/Timeline/Timeline.tsx @@ -1,7 +1,7 @@ import React, { isValidElement } from "react"; import View from "components/View"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Timeline.module.css"; diff --git a/packages/reshaped/src/components/Toast/ToastContainer.tsx b/packages/reshaped/src/components/Toast/ToastContainer.tsx index cf03ff00..056bd704 100644 --- a/packages/reshaped/src/components/Toast/ToastContainer.tsx +++ b/packages/reshaped/src/components/Toast/ToastContainer.tsx @@ -5,7 +5,7 @@ import { checkKeyboardMode } from "@reshaped/utilities/internal"; import React from "react"; import { onNextFrame } from "utilities/animation"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import Toast from "./Toast"; import { timeouts } from "./Toast.constants"; diff --git a/packages/reshaped/src/components/Toast/ToastRegion.tsx b/packages/reshaped/src/components/Toast/ToastRegion.tsx index d9e4674e..87c960de 100644 --- a/packages/reshaped/src/components/Toast/ToastRegion.tsx +++ b/packages/reshaped/src/components/Toast/ToastRegion.tsx @@ -3,7 +3,7 @@ import { focusableSelector } from "@reshaped/utilities/internal"; import React from "react"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import ToastContext from "./Toast.context"; import s from "./Toast.module.css"; diff --git a/packages/reshaped/src/components/View/View.tsx b/packages/reshaped/src/components/View/View.tsx index 669c0b93..c15be428 100644 --- a/packages/reshaped/src/components/View/View.tsx +++ b/packages/reshaped/src/components/View/View.tsx @@ -1,9 +1,10 @@ +import { classNames } from "@reshaped/utilities"; import React, { isValidElement } from "react"; import Divider, { type DividerProps } from "components/Divider"; import Hidden from "components/Hidden"; import { resolveMixin } from "styles/mixin"; -import { classNames, responsiveClassNames, responsiveVariables } from "utilities/props"; +import { responsiveClassNames, responsiveVariables } from "utilities/props"; import s from "./View.module.css"; diff --git a/packages/reshaped/src/components/_private/Aligner/Aligner.tsx b/packages/reshaped/src/components/_private/Aligner/Aligner.tsx index 372fb3fe..11339a3b 100644 --- a/packages/reshaped/src/components/_private/Aligner/Aligner.tsx +++ b/packages/reshaped/src/components/_private/Aligner/Aligner.tsx @@ -7,7 +7,7 @@ * on the --rs-p, --rs-p-v and --rs-p-h css variables */ -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Aligner.module.css"; diff --git a/packages/reshaped/src/components/_private/Expandable/Expandable.tsx b/packages/reshaped/src/components/_private/Expandable/Expandable.tsx index d5866290..f1458015 100644 --- a/packages/reshaped/src/components/_private/Expandable/Expandable.tsx +++ b/packages/reshaped/src/components/_private/Expandable/Expandable.tsx @@ -4,7 +4,7 @@ import React from "react"; import useIsomorphicLayoutEffect from "hooks/useIsomorphicLayoutEffect"; import { onNextFrame } from "utilities/animation"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import s from "./Expandable.module.css"; import * as T from "./Expandable.types"; diff --git a/packages/reshaped/src/core/Actionable/Actionable.tsx b/packages/reshaped/src/core/Actionable/Actionable.tsx index 3e9fbeca..5a701c76 100644 --- a/packages/reshaped/src/core/Actionable/Actionable.tsx +++ b/packages/reshaped/src/core/Actionable/Actionable.tsx @@ -3,7 +3,7 @@ import React, { forwardRef } from "react"; import * as keys from "constants/keys"; -import { classNames } from "utilities/props"; +import { classNames } from "@reshaped/utilities"; import type * as T from "./Actionable.types"; diff --git a/packages/reshaped/src/index.ts b/packages/reshaped/src/index.ts index 6438fa87..4d6b6410 100644 --- a/packages/reshaped/src/index.ts +++ b/packages/reshaped/src/index.ts @@ -221,8 +221,8 @@ export { default as useToggle } from "hooks/useToggle"; /** * Utility functions */ -export { classNames, responsivePropDependency } from "utilities/props"; -export { TrapFocus } from "@reshaped/utilities"; +export { responsivePropDependency } from "utilities/props"; +export { TrapFocus, classNames } from "@reshaped/utilities"; /** * Types diff --git a/packages/reshaped/src/utilities/props.ts b/packages/reshaped/src/utilities/props.ts index fc2fe4e8..960643fa 100644 --- a/packages/reshaped/src/utilities/props.ts +++ b/packages/reshaped/src/utilities/props.ts @@ -3,23 +3,6 @@ import type * as G from "types/global"; type Value = string | boolean | number | undefined; type ClassNameResolver = string | ((value: Value) => string); -/** - * Resolve an array of values into a classname string - */ -export const classNames = (...args: G.ClassName[]): string => { - return args - .reduce((acc, cur) => { - if (Array.isArray(cur)) { - const className = classNames(...cur); - if (!className) return acc; - return `${acc} ${className}`; - } - if (cur) return `${acc} ${cur}`; - return acc; - }, "") - .trim(); -}; - const applyClassName = ( passedClassName: ClassNameResolver, value: Value, diff --git a/packages/reshaped/src/utilities/tests/props.test.ts b/packages/reshaped/src/utilities/tests/props.test.ts index 01caddf3..bc4fa44b 100644 --- a/packages/reshaped/src/utilities/tests/props.test.ts +++ b/packages/reshaped/src/utilities/tests/props.test.ts @@ -1,25 +1,6 @@ import { describe, test, expect } from "vitest"; -import { classNames, responsiveClassNames, responsivePropDependency } from "utilities/props"; - -describe("Utilities/Props/classNames", () => { - test("returns a single className", () => { - expect(classNames("foo")).toBe("foo"); - }); - - test("returns multiple classNames", () => { - expect(classNames(["foo", "bar"])).toBe("foo bar"); - }); - - test("ignores falsy values", () => { - const flag = false; - expect(classNames(["foo", flag && "baz", undefined, null, "bar"])).toBe("foo bar"); - }); - - test("handles nested arrays", () => { - expect(classNames(["foo", ["bar", "baz"]])).toBe("foo bar baz"); - }); -}); +import { responsiveClassNames, responsivePropDependency } from "utilities/props"; describe("Utilities/Props/responsiveClassNames", () => { const s = { "--size-small": "small", "--size-medium--l": "medium" }; diff --git a/packages/utilities/src/flyout/utilities/tests/isFullyVisible.test.ts b/packages/utilities/src/flyout/utilities/tests/isFullyVisible.test.ts index 393e3542..5392394b 100644 --- a/packages/utilities/src/flyout/utilities/tests/isFullyVisible.test.ts +++ b/packages/utilities/src/flyout/utilities/tests/isFullyVisible.test.ts @@ -1,6 +1,5 @@ -import { expect, test, describe } from "vitest"; - import isFullyVisible from "flyout/utilities/isFullyVisible"; +import { expect, test, describe } from "vitest"; describe("flyout/isFullyVisible", () => { test("returns true when flyout is fully visible within visual container", () => { diff --git a/packages/utilities/src/helpers/classNames.ts b/packages/utilities/src/helpers/classNames.ts new file mode 100644 index 00000000..8fd3c991 --- /dev/null +++ b/packages/utilities/src/helpers/classNames.ts @@ -0,0 +1,21 @@ +type ClassNameValue = string | null | undefined | false; +export type ClassName = ClassNameValue | ClassNameValue[] | ClassName[]; + +/** + * Resolve an array of values into a classname string + */ +const classNames = (...args: ClassName[]): string => { + return args + .reduce((acc, cur) => { + if (Array.isArray(cur)) { + const className = classNames(...cur); + if (!className) return acc; + return `${acc} ${className}`; + } + if (cur) return `${acc} ${cur}`; + return acc; + }, "") + .trim(); +}; + +export default classNames; diff --git a/packages/utilities/src/helpers/index.ts b/packages/utilities/src/helpers/index.ts new file mode 100644 index 00000000..fae892a8 --- /dev/null +++ b/packages/utilities/src/helpers/index.ts @@ -0,0 +1,2 @@ +export { default as classNames, type ClassName } from "./classNames"; +export { default as rafThrottle } from "./rafThrottle"; diff --git a/packages/utilities/src/helpers/tests/classNames.test.ts b/packages/utilities/src/helpers/tests/classNames.test.ts new file mode 100644 index 00000000..ddf66659 --- /dev/null +++ b/packages/utilities/src/helpers/tests/classNames.test.ts @@ -0,0 +1,80 @@ +import { expect, test, describe } from "vitest"; + +import classNames from "../classNames"; + +describe("helpers/classNames", () => { + test("returns empty string when no arguments are provided", () => { + expect(classNames()).toBe(""); + }); + + test("returns a single class name", () => { + expect(classNames("foo")).toBe("foo"); + }); + + test("concatenates multiple class names", () => { + expect(classNames("foo", "bar", "baz")).toBe("foo bar baz"); + }); + + test("filters out null values", () => { + expect(classNames("foo", null, "bar")).toBe("foo bar"); + expect(classNames(null, "foo", null)).toBe("foo"); + expect(classNames(null, null)).toBe(""); + }); + + test("filters out undefined values", () => { + expect(classNames("foo", undefined, "bar")).toBe("foo bar"); + expect(classNames(undefined, "foo", undefined)).toBe("foo"); + expect(classNames(undefined, undefined)).toBe(""); + }); + + test("filters out false values", () => { + expect(classNames("foo", false, "bar")).toBe("foo bar"); + expect(classNames(false, "foo", false)).toBe("foo"); + expect(classNames(false, false)).toBe(""); + }); + + test("handles arrays of class names", () => { + expect(classNames(["foo", "bar"])).toBe("foo bar"); + expect(classNames(["foo", "bar"], "baz")).toBe("foo bar baz"); + expect(classNames("foo", ["bar", "baz"])).toBe("foo bar baz"); + }); + + test("handles nested arrays", () => { + expect(classNames(["foo", ["bar", "baz"]])).toBe("foo bar baz"); + expect(classNames([["foo", "bar"], "baz"])).toBe("foo bar baz"); + expect(classNames([["foo"], ["bar"], ["baz"]])).toBe("foo bar baz"); + }); + + test("filters out falsy values in arrays", () => { + expect(classNames(["foo", null, "bar"])).toBe("foo bar"); + expect(classNames(["foo", undefined, "bar"])).toBe("foo bar"); + expect(classNames(["foo", false, "bar"])).toBe("foo bar"); + expect(classNames([null, undefined, false])).toBe(""); + }); + + test("handles deeply nested arrays with falsy values", () => { + expect(classNames([["foo", null], [undefined, "bar"], false])).toBe("foo bar"); + expect(classNames(["foo", [null, undefined, ["bar", false, "baz"]]])).toBe("foo bar baz"); + }); + + test("handles empty arrays", () => { + expect(classNames([])).toBe(""); + expect(classNames("foo", [], "bar")).toBe("foo bar"); + expect(classNames([[], []])).toBe(""); + }); + + test("handles empty strings", () => { + expect(classNames("", "foo")).toBe("foo"); + expect(classNames("foo", "", "bar")).toBe("foo bar"); + expect(classNames("", "", "")).toBe(""); + }); + + test("handles conditional class names", () => { + const isActive = true; + const isDisabled = false; + + expect(classNames("button", isActive && "active", isDisabled && "disabled")).toBe( + "button active" + ); + }); +}); diff --git a/packages/utilities/src/i18n/index.ts b/packages/utilities/src/i18n/index.ts new file mode 100644 index 00000000..a9a858c9 --- /dev/null +++ b/packages/utilities/src/i18n/index.ts @@ -0,0 +1 @@ +export { default as isRTL } from "./isRTL"; diff --git a/packages/utilities/src/index.ts b/packages/utilities/src/index.ts index 42af9bed..5a0b2892 100644 --- a/packages/utilities/src/index.ts +++ b/packages/utilities/src/index.ts @@ -1,2 +1,5 @@ export { default as Flyout } from "./flyout"; export { default as TrapFocus } from "./a11y/TrapFocus"; + +export { default as isRTL } from "./i18n/isRTL"; +export { classNames, type ClassName } from "./helpers"; diff --git a/packages/utilities/tsconfig.json b/packages/utilities/tsconfig.json index c6660c0a..2494061b 100644 --- a/packages/utilities/tsconfig.json +++ b/packages/utilities/tsconfig.json @@ -10,5 +10,5 @@ "paths": { "*": ["*"] } }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "src/**/*.test.ts"] + "exclude": ["node_modules", "dist"] }