Skip to content
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
6 changes: 6 additions & 0 deletions .changeset/angry-moose-promise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@launchpad-ui/components": minor
"@launchpad-ui/icons": minor
---

Use `ref` prop instead of `forwardRef` and drop React 18 support
4 changes: 2 additions & 2 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
"react-router": "7.0.1"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"react": "19.0.0",
Expand Down
30 changes: 13 additions & 17 deletions packages/components/src/Alert.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { VariantProps } from 'class-variance-authority';
import type { ForwardedRef, HTMLAttributes } from 'react';
import type { HTMLAttributes, RefObject } from 'react';

import { StatusIcon } from '@launchpad-ui/icons';
import { useControlledState } from '@react-stately/utils';
import { cva } from 'class-variance-authority';
import { forwardRef } from 'react';
import { HeadingContext, Provider } from 'react-aria-components';

import { IconButton } from './IconButton';
Expand Down Expand Up @@ -37,21 +36,20 @@ interface AlertProps extends HTMLAttributes<HTMLDivElement>, AlertVariants {
isDismissable?: boolean;
isOpen?: boolean;
onDismiss?: () => void;
ref?: RefObject<HTMLDivElement | null>;
}

const _Alert = (
{
className,
children,
status = 'neutral',
variant = 'default',
isDismissable,
isOpen,
onDismiss,
...props
}: AlertProps,
ref: ForwardedRef<HTMLDivElement>,
) => {
const Alert = ({
className,
children,
status = 'neutral',
variant = 'default',
isDismissable,
isOpen,
onDismiss,
ref,
...props
}: AlertProps) => {
const [open, setOpen] = useControlledState(isOpen, true, (val) => !val && onDismiss?.());

return open ? (
Expand All @@ -75,7 +73,5 @@ const _Alert = (
) : null;
};

const Alert = forwardRef(_Alert);

export { Alert };
export type { AlertProps };
42 changes: 23 additions & 19 deletions packages/components/src/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import type { forwardRefType } from '@react-types/shared';
import type { ForwardedRef } from 'react';
import type { BreadcrumbProps, BreadcrumbsProps, ContextValue } from 'react-aria-components';
import type { RefObject } from 'react';
import type {
BreadcrumbProps as AriaBreadcrumbProps,
BreadcrumbsProps as AriaBreadcrumbsProps,
ContextValue,
} from 'react-aria-components';
import type { LinkProps } from './Link';

import { cva } from 'class-variance-authority';
import { createContext, forwardRef } from 'react';
import { createContext } from 'react';
import {
Breadcrumb as AriaBreadcrumb,
Breadcrumbs as AriaBreadcrumbs,
Expand All @@ -19,21 +22,29 @@ const crumb = cva(styles.crumb);

const LinkContext = createContext<ContextValue<LinkProps, HTMLAnchorElement>>(null);

const _Breadcrumbs = <T extends object>(
{ className, ...props }: BreadcrumbsProps<T>,
ref: ForwardedRef<HTMLOListElement>,
) => {
return <AriaBreadcrumbs {...props} ref={ref} className={crumbs({ className })} />;
};
interface BreadcrumbsProps<T extends object> extends AriaBreadcrumbsProps<T> {
ref?: RefObject<HTMLOListElement | null>;
}

interface BreadcrumbProps extends AriaBreadcrumbProps {
ref?: RefObject<HTMLLIElement | null>;
}

/**
* Breadcrumbs display a hierarchy of links to the current page or resource in an application.
*
* https://react-spectrum.adobe.com/react-aria/Breadcrumbs.html
*/
const Breadcrumbs = (forwardRef as forwardRefType)(_Breadcrumbs);
const Breadcrumbs = <T extends object>({ className, ref, ...props }: BreadcrumbsProps<T>) => {
return <AriaBreadcrumbs {...props} ref={ref} className={crumbs({ className })} />;
};

const _Breadcrumb = (props: BreadcrumbProps, ref: ForwardedRef<HTMLLIElement>) => {
/**
* A Breadcrumb represents an individual item in a `<Breadcrumbs>` list.
*
* https://react-spectrum.adobe.com/react-aria/Breadcrumbs.html
*/
const Breadcrumb = ({ ref, ...props }: BreadcrumbProps) => {
return (
<AriaBreadcrumb
{...props}
Expand All @@ -49,12 +60,5 @@ const _Breadcrumb = (props: BreadcrumbProps, ref: ForwardedRef<HTMLLIElement>) =
);
};

/**
* A Breadcrumb represents an individual item in a `<Breadcrumbs>` list.
*
* https://react-spectrum.adobe.com/react-aria/Breadcrumbs.html
*/
const Breadcrumb = forwardRef(_Breadcrumb);

export { Breadcrumbs, Breadcrumb, LinkContext };
export type { BreadcrumbsProps, BreadcrumbProps };
25 changes: 11 additions & 14 deletions packages/components/src/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { VariantProps } from 'class-variance-authority';
import type { ForwardedRef } from 'react';
import type { RefObject } from 'react';
import type { ButtonProps as AriaButtonProps } from 'react-aria-components';

import { cva, cx } from 'class-variance-authority';
import { forwardRef, useContext } from 'react';
import { useContext } from 'react';
import {
Button as AriaButton,
Provider,
Expand Down Expand Up @@ -40,12 +40,16 @@ const button = cva(styles.base, {
});

interface ButtonVariants extends VariantProps<typeof button> {}
interface ButtonProps extends AriaButtonProps, ButtonVariants {}
interface ButtonProps extends AriaButtonProps, ButtonVariants {
ref?: RefObject<HTMLButtonElement | null>;
}

const _Button = (
{ size = 'medium', variant = 'default', ...props }: ButtonProps,
ref: ForwardedRef<HTMLButtonElement>,
) => {
/**
* A button allows a user to perform an action, with mouse, touch, and keyboard interactions.
*
* https://react-spectrum.adobe.com/react-aria/Button.html
*/
const Button = ({ size = 'medium', variant = 'default', ref, ...props }: ButtonProps) => {
const selectContext = useSlottedContext(SelectContext);
const state = useContext(SelectStateContext);
const ctx = useContext(PerceivableContext);
Expand Down Expand Up @@ -73,12 +77,5 @@ const _Button = (
);
};

/**
* A button allows a user to perform an action, with mouse, touch, and keyboard interactions.
*
* https://react-spectrum.adobe.com/react-aria/Button.html
*/
const Button = forwardRef(_Button);

export { Button, button };
export type { ButtonProps, ButtonVariants };
16 changes: 8 additions & 8 deletions packages/components/src/ButtonGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { Orientation } from '@react-types/shared';
import type { VariantProps } from 'class-variance-authority';
import type { ForwardedRef } from 'react';
import type { RefObject } from 'react';
import type { GroupProps } from 'react-aria-components';

import { cva } from 'class-variance-authority';
import { forwardRef } from 'react';
import {
ButtonContext,
Group,
Expand Down Expand Up @@ -34,12 +33,15 @@ const buttonGroup = cva(styles.base, {

interface ButtonGroupProps extends GroupProps, VariantProps<typeof buttonGroup> {
orientation?: Orientation | null;
ref?: RefObject<HTMLDivElement | null>;
}

const _ButtonGroup = (
{ spacing = 'basic', orientation = 'horizontal', ...props }: ButtonGroupProps,
ref: ForwardedRef<HTMLDivElement>,
) => {
const ButtonGroup = ({
spacing = 'basic',
orientation = 'horizontal',
ref,
...props
}: ButtonGroupProps) => {
return (
<Group
{...props}
Expand All @@ -63,7 +65,5 @@ const _ButtonGroup = (
);
};

const ButtonGroup = forwardRef(_ButtonGroup);

export { ButtonGroup };
export type { ButtonGroupProps };
72 changes: 34 additions & 38 deletions packages/components/src/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import type { CalendarDate } from '@internationalized/date';
import type { RangeValue } from '@react-types/shared';
import type { ForwardedRef, HTMLAttributes } from 'react';
import type { HTMLAttributes, RefObject } from 'react';
import type {
CalendarCellProps,
CalendarCellProps as AriaCalendarCellProps,
CalendarProps as AriaCalendarProps,
RangeCalendarProps as AriaRangeCalendarProps,
CalendarGridBodyProps,
CalendarGridHeaderProps,
CalendarGridProps,
CalendarHeaderCellProps,
CalendarProps,
DateRange,
DateValue,
RangeCalendarProps,
} from 'react-aria-components';
import type { ButtonProps } from './Button';

import { cva, cx } from 'class-variance-authority';
import { forwardRef, useState } from 'react';
import { useState } from 'react';
import {
Calendar as AriaCalendar,
CalendarCell as AriaCalendarCell,
Expand All @@ -35,20 +35,37 @@ import {
import { Button, button } from './Button';
import styles from './styles/Calendar.module.css';

interface CalendarPickerProps extends HTMLAttributes<HTMLDivElement> {}
interface CalendarPickerProps extends HTMLAttributes<HTMLDivElement> {
ref?: RefObject<HTMLDivElement | null>;
}

interface PresetProps extends Omit<ButtonProps, 'value'> {
value: CalendarDate | RangeValue<CalendarDate>;
ref?: RefObject<HTMLButtonElement | null>;
}

const calendar = cva(styles.calendar);
const cell = cva(styles.cell);
const range = cva(styles.range);

const _Calendar = <T extends DateValue>(
props: CalendarProps<T>,
ref: ForwardedRef<HTMLDivElement>,
) => {
interface CalendarProps<T extends DateValue> extends AriaCalendarProps<T> {
ref?: RefObject<HTMLDivElement | null>;
}

interface CalendarCellProps extends AriaCalendarCellProps {
ref?: RefObject<HTMLTableCellElement | null>;
}

interface RangeCalendarProps<T extends DateValue> extends AriaRangeCalendarProps<T> {
ref?: RefObject<HTMLDivElement | null>;
}

/**
* A calendar displays one or more date grids and allows users to select a single date.
*
* https://react-spectrum.adobe.com/react-aria/Calendar.html
*/
const Calendar = <T extends DateValue>({ ref, ...props }: CalendarProps<T>) => {
return (
<AriaCalendar
{...props}
Expand All @@ -61,13 +78,11 @@ const _Calendar = <T extends DateValue>(
};

/**
* A calendar displays one or more date grids and allows users to select a single date.
* A calendar cell displays a date cell within a calendar grid which can be selected by the user.
*
* https://react-spectrum.adobe.com/react-aria/Calendar.html
*/
const Calendar = forwardRef(_Calendar);

const _CalendarCell = (props: CalendarCellProps, ref: ForwardedRef<HTMLTableCellElement>) => {
const CalendarCell = ({ ref, ...props }: CalendarCellProps) => {
return (
<AriaCalendarCell
{...props}
Expand All @@ -80,16 +95,11 @@ const _CalendarCell = (props: CalendarCellProps, ref: ForwardedRef<HTMLTableCell
};

/**
* A calendar cell displays a date cell within a calendar grid which can be selected by the user.
* A range calendar displays one or more date grids and allows users to select a contiguous range of dates.
*
* https://react-spectrum.adobe.com/react-aria/Calendar.html
* https://react-spectrum.adobe.com/react-aria/RangeCalendar.html
*/
const CalendarCell = forwardRef(_CalendarCell);

const _RangeCalendar = <T extends DateValue>(
props: RangeCalendarProps<T>,
ref: ForwardedRef<HTMLDivElement>,
) => {
const RangeCalendar = <T extends DateValue>({ ref, ...props }: RangeCalendarProps<T>) => {
return (
<AriaRangeCalendar
{...props}
Expand All @@ -101,17 +111,7 @@ const _RangeCalendar = <T extends DateValue>(
);
};

/**
* A range calendar displays one or more date grids and allows users to select a contiguous range of dates.
*
* https://react-spectrum.adobe.com/react-aria/RangeCalendar.html
*/
const RangeCalendar = forwardRef(_RangeCalendar);

const _CalendarPicker = (
{ children, className, ...props }: CalendarPickerProps,
ref: ForwardedRef<HTMLDivElement>,
) => {
const CalendarPicker = ({ children, className, ref, ...props }: CalendarPickerProps) => {
const [value, onChange] = useState<DateValue>();
const [range, onChangeRange] = useState<DateRange | null>();
const [focusedValue, onFocusChange] = useState<DateValue>();
Expand All @@ -133,9 +133,7 @@ const _CalendarPicker = (
);
};

const CalendarPicker = forwardRef(_CalendarPicker);

const _Preset = ({ value, ...props }: PresetProps, ref: ForwardedRef<HTMLButtonElement>) => {
const Preset = ({ value, ref, ...props }: PresetProps) => {
const context = useSlottedContext(CalendarContext);
const rangeContext = useSlottedContext(RangeCalendarContext);
const onPress = () => {
Expand All @@ -150,8 +148,6 @@ const _Preset = ({ value, ...props }: PresetProps, ref: ForwardedRef<HTMLButtonE
return <Button ref={ref} size="small" variant="minimal" {...props} onPress={onPress} />;
};

const Preset = forwardRef(_Preset);

export {
Calendar,
CalendarCell,
Expand Down
Loading
Loading