Skip to content

feat: add full ESM support #125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .babelrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = (api) => ({
export default (api) => ({
presets: [
['env-modules', { modules: api.env() === 'cjs' ? 'commonjs' : false }],
['@babel/react', { runtime: 'automatic' }],
Expand Down
2 changes: 1 addition & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export default tseslint.config(
ignoreRestSiblings: false,
},
],
'react/prop-types': 'off',
},
},
{
Expand Down Expand Up @@ -82,7 +83,6 @@ export default tseslint.config(
'@typescript-eslint/no-unused-expressions': 'off',
'padded-blocks': 'off',
'react/no-multi-comp': 'off',
'react/prop-types': 'off',
},
},
);
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"url": "git+https://github.com/react-restart/ui.git"
},
"license": "MIT",
"main": "cjs/index.js",
"type": "module",
"main": "lib/index.js",
"module": "lib/index.js",
"types": "lib/index.d.ts",
"exports": {
Expand Down Expand Up @@ -100,7 +101,7 @@
"@restart/hooks": "^0.6.2",
"@types/warning": "^3.0.3",
"dequal": "^2.0.3",
"dom-helpers": "^5.2.0",
"dom-helpers": "^6.0.1",
"uncontrollable": "^9.0.0",
"warning": "^4.0.3"
},
Expand Down
2 changes: 1 addition & 1 deletion src/Anchor.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';

import useEventCallback from '@restart/hooks/useEventCallback';
import { useButtonProps } from './Button';
import { useButtonProps } from './Button.js';

export function isTrivialHref(href?: string) {
return !href || href.trim() === '#';
Expand Down
28 changes: 14 additions & 14 deletions src/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ import useForceUpdate from '@restart/hooks/useForceUpdate';
import useEventListener from '@restart/hooks/useEventListener';
import useEventCallback from '@restart/hooks/useEventCallback';

import DropdownContext from './DropdownContext';
import DropdownContext from './DropdownContext.js';
import DropdownMenu, {
DropdownMenuProps,
UseDropdownMenuMetadata,
UseDropdownMenuOptions,
} from './DropdownMenu';
type DropdownMenuProps,
type UseDropdownMenuMetadata,
type UseDropdownMenuOptions,
} from './DropdownMenu.js';
import DropdownToggle, {
DropdownToggleProps,
UseDropdownToggleMetadata,
type DropdownToggleProps,
type UseDropdownToggleMetadata,
isRoleMenu,
} from './DropdownToggle';
import DropdownItem, { DropdownItemProps } from './DropdownItem';
import SelectableContext from './SelectableContext';
import { SelectCallback } from './types';
import { dataAttr } from './DataKey';
import { Placement } from './usePopper';
import useWindow from './useWindow';
} from './DropdownToggle.js';
import DropdownItem, { type DropdownItemProps } from './DropdownItem.js';
import SelectableContext from './SelectableContext.js';
import type { SelectCallback } from './types.js';
import { dataAttr } from './DataKey.js';
import type { Placement } from './usePopper.js';
import useWindow from './useWindow.js';

export type {
DropdownMenuProps,
Expand Down
2 changes: 1 addition & 1 deletion src/DropdownContext.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import type { Placement } from './usePopper';
import type { Placement } from './usePopper.js';

export type DropdownContextValue = {
toggle: (
Expand Down
10 changes: 5 additions & 5 deletions src/DropdownItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import * as React from 'react';
import { useContext } from 'react';
import useEventCallback from '@restart/hooks/useEventCallback';

import SelectableContext, { makeEventKey } from './SelectableContext';
import NavContext from './NavContext';
import SelectableContext, { makeEventKey } from './SelectableContext.js';
import NavContext from './NavContext.js';

import { EventKey, DynamicRefForwardingComponent } from './types';
import Button from './Button';
import { dataAttr } from './DataKey';
import type { EventKey, DynamicRefForwardingComponent } from './types.js';
import Button from './Button.js';
import { dataAttr } from './DataKey.js';

export interface DropdownItemProps extends React.HTMLAttributes<HTMLElement> {
/**
Expand Down
20 changes: 12 additions & 8 deletions src/DropdownMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { useContext, useRef } from 'react';
import * as React from 'react';
import useCallbackRef from '@restart/hooks/useCallbackRef';
import DropdownContext, { DropdownContextValue } from './DropdownContext';
import DropdownContext, {
type DropdownContextValue,
} from './DropdownContext.js';
import usePopper, {
UsePopperOptions,
Placement,
Offset,
UsePopperState,
} from './usePopper';
import useClickOutside, { ClickOutsideOptions } from './useClickOutside';
import mergeOptionsWithPopperConfig from './mergeOptionsWithPopperConfig';
type UsePopperOptions,
type Placement,
type Offset,
type UsePopperState,
} from './usePopper.js';
import useClickOutside, {
type ClickOutsideOptions,
} from './useClickOutside.js';
import mergeOptionsWithPopperConfig from './mergeOptionsWithPopperConfig.js';

export interface UseDropdownMenuOptions {
/**
Expand Down
4 changes: 3 additions & 1 deletion src/DropdownToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useContext, useCallback, useId } from 'react';
import * as React from 'react';
import DropdownContext, { DropdownContextValue } from './DropdownContext';
import DropdownContext, {
type DropdownContextValue,
} from './DropdownContext.js';

export const isRoleMenu = (el: HTMLElement) =>
el.getAttribute('role')?.toLowerCase() === 'menu';
Expand Down
8 changes: 4 additions & 4 deletions src/ImperativeTransition.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import useMergedRefs from '@restart/hooks/useMergedRefs';
import useEventCallback from '@restart/hooks/useEventCallback';
import useIsomorphicEffect from '@restart/hooks/useIsomorphicEffect';
import { useRef, cloneElement, useState } from 'react';
import { TransitionComponent, TransitionProps } from './types';
import NoopTransition from './NoopTransition';
import RTGTransition from './RTGTransition';
import { getChildRef } from './utils';
import type { TransitionComponent, TransitionProps } from './types.js';
import NoopTransition from './NoopTransition.js';
import RTGTransition from './RTGTransition.js';
import { getChildRef } from './utils.js';

export interface TransitionFunctionOptions {
in: boolean;
Expand Down
17 changes: 9 additions & 8 deletions src/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable react/prop-types */

import activeElement from 'dom-helpers/activeElement';
import contains from 'dom-helpers/contains';
import canUseDOM from 'dom-helpers/canUseDOM';
Expand All @@ -19,12 +17,15 @@ import useWillUnmount from '@restart/hooks/useWillUnmount';

import usePrevious from '@restart/hooks/usePrevious';
import useEventCallback from '@restart/hooks/useEventCallback';
import ModalManager from './ModalManager';
import useWaitForDOMRef, { DOMContainer } from './useWaitForDOMRef';
import { TransitionCallbacks, TransitionComponent } from './types';
import useWindow from './useWindow';
import { renderTransition, TransitionHandler } from './ImperativeTransition';
import { isEscKey } from './utils';
import ModalManager from './ModalManager.js';
import useWaitForDOMRef, { type DOMContainer } from './useWaitForDOMRef.js';
import type { TransitionCallbacks, TransitionComponent } from './types.js';
import useWindow from './useWindow.js';
import {
renderTransition,
type TransitionHandler,
} from './ImperativeTransition.js';
import { isEscKey } from './utils.js';

let manager: ModalManager;

Expand Down
4 changes: 2 additions & 2 deletions src/ModalManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import css from 'dom-helpers/css';
import { dataAttr } from './DataKey';
import getBodyScrollbarWidth from './getScrollbarWidth';
import { dataAttr } from './DataKey.js';
import getBodyScrollbarWidth from './getScrollbarWidth.js';

export interface ModalInstance {
dialog: Element;
Expand Down
17 changes: 10 additions & 7 deletions src/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ import * as React from 'react';
import { useContext, useEffect, useRef } from 'react';
import useForceUpdate from '@restart/hooks/useForceUpdate';
import useMergedRefs from '@restart/hooks/useMergedRefs';
import NavContext from './NavContext';
import SelectableContext, { makeEventKey } from './SelectableContext';
import TabContext from './TabContext';
import {
import NavContext from './NavContext.js';
import SelectableContext, { makeEventKey } from './SelectableContext.js';
import TabContext from './TabContext.js';
import type {
EventKey,
DynamicRefForwardingComponent,
SelectCallback,
} from './types';
import { dataAttr, dataProp } from './DataKey';
import NavItem, { UseNavItemOptions, NavItemProps } from './NavItem';
} from './types.js';
import { dataAttr, dataProp } from './DataKey.js';
import NavItem, {
type UseNavItemOptions,
type NavItemProps,
} from './NavItem.js';

export type { UseNavItemOptions, NavItemProps };

Expand Down
2 changes: 1 addition & 1 deletion src/NavContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { EventKey } from './types';
import type { EventKey } from './types.js';

interface NavContextType {
role?: string; // used by NavItem to determine it's role
Expand Down
12 changes: 6 additions & 6 deletions src/NavItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import * as React from 'react';
import { useContext } from 'react';
import useEventCallback from '@restart/hooks/useEventCallback';

import NavContext from './NavContext';
import SelectableContext, { makeEventKey } from './SelectableContext';
import { EventKey, DynamicRefForwardingComponent } from './types';
import Button from './Button';
import { dataAttr } from './DataKey';
import TabContext from './TabContext';
import NavContext from './NavContext.js';
import SelectableContext, { makeEventKey } from './SelectableContext.js';
import type { EventKey, DynamicRefForwardingComponent } from './types.js';
import Button from './Button.js';
import { dataAttr } from './DataKey.js';
import TabContext from './TabContext.js';

export interface NavItemProps extends React.HTMLAttributes<HTMLElement> {
/**
Expand Down
4 changes: 2 additions & 2 deletions src/NoopTransition.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import useEventCallback from '@restart/hooks/useEventCallback';
import useMergedRefs from '@restart/hooks/useMergedRefs';
import { cloneElement, useEffect, useRef } from 'react';
import { TransitionProps } from './types';
import { getChildRef } from './utils';
import type { TransitionProps } from './types.js';
import { getChildRef } from './utils.js';

function NoopTransition({
children,
Expand Down
25 changes: 14 additions & 11 deletions src/Overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@ import useCallbackRef from '@restart/hooks/useCallbackRef';
import useMergedRefs from '@restart/hooks/useMergedRefs';
import { useState } from 'react';
import usePopper, {
Offset,
Placement,
UsePopperOptions,
UsePopperState,
VirtualElement,
} from './usePopper';
import useRootClose, { RootCloseOptions } from './useRootClose';
import useWaitForDOMRef, { DOMContainer } from './useWaitForDOMRef';
import { TransitionCallbacks, TransitionComponent } from './types';
import mergeOptionsWithPopperConfig from './mergeOptionsWithPopperConfig';
import { renderTransition, TransitionHandler } from './ImperativeTransition';
type Offset,
type Placement,
type UsePopperOptions,
type UsePopperState,
type VirtualElement,
} from './usePopper.js';
import useRootClose, { type RootCloseOptions } from './useRootClose.js';
import useWaitForDOMRef, { type DOMContainer } from './useWaitForDOMRef.js';
import type { TransitionCallbacks, TransitionComponent } from './types.js';
import mergeOptionsWithPopperConfig from './mergeOptionsWithPopperConfig.js';
import {
renderTransition,
type TransitionHandler,
} from './ImperativeTransition.js';

export interface OverlayArrowProps extends Record<string, any> {
ref: React.RefCallback<HTMLElement>;
Expand Down
2 changes: 1 addition & 1 deletion src/Portal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ReactDOM from 'react-dom';

import * as React from 'react';
import useWaitForDOMRef, { DOMContainer } from './useWaitForDOMRef';
import useWaitForDOMRef, { type DOMContainer } from './useWaitForDOMRef.js';

export interface PortalProps {
children: React.ReactElement;
Expand Down
4 changes: 2 additions & 2 deletions src/RTGTransition.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import useRTGTransitionProps, {
TransitionProps,
} from './useRTGTransitionProps';
type TransitionProps,
} from './useRTGTransitionProps.js';

export type RTGTransitionProps = TransitionProps & {
component: React.ElementType;
Expand Down
2 changes: 1 addition & 1 deletion src/SelectableContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { EventKey, SelectCallback } from './types';
import type { EventKey, SelectCallback } from './types.js';

const SelectableContext = React.createContext<SelectCallback | null>(null);

Expand Down
2 changes: 1 addition & 1 deletion src/TabContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { EventKey, SelectCallback, TransitionComponent } from './types';
import type { EventKey, SelectCallback, TransitionComponent } from './types.js';

export interface TabContextType {
onSelect: SelectCallback;
Expand Down
10 changes: 5 additions & 5 deletions src/TabPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import * as React from 'react';
import { useContext } from 'react';

import TabContext from './TabContext';
import SelectableContext, { makeEventKey } from './SelectableContext';
import {
import TabContext from './TabContext.js';
import SelectableContext, { makeEventKey } from './SelectableContext.js';
import type {
EventKey,
DynamicRefForwardingComponent,
TransitionCallbacks,
TransitionComponent,
} from './types';
import NoopTransition from './NoopTransition';
} from './types.js';
import NoopTransition from './NoopTransition.js';

export interface TabPanelProps
extends TransitionCallbacks,
Expand Down
8 changes: 4 additions & 4 deletions src/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import * as React from 'react';
import { useId, useMemo } from 'react';
import { useUncontrolledProp } from 'uncontrollable';

import TabContext, { TabContextType } from './TabContext';
import SelectableContext from './SelectableContext';
import { EventKey, SelectCallback, TransitionComponent } from './types';
import TabPanel, { TabPanelProps } from './TabPanel';
import TabContext, { type TabContextType } from './TabContext.js';
import SelectableContext from './SelectableContext.js';
import { EventKey, SelectCallback, TransitionComponent } from './types.js';
import TabPanel, { TabPanelProps } from './TabPanel.js';

export type { TabPanelProps };
export interface TabsProps extends React.PropsWithChildren<unknown> {
Expand Down
8 changes: 4 additions & 4 deletions src/Waypoint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import useCallbackRef from '@restart/hooks/useCallbackRef';
import * as React from 'react';

import useWaypoint, {
WaypointOptions,
WaypointEvent,
Position,
} from './useWaypoint';
type WaypointOptions,
type WaypointEvent,
type Position,
} from './useWaypoint.js';

export { Position };
export type { WaypointEvent };
Expand Down
Loading