Skip to content
Open
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
10 changes: 10 additions & 0 deletions .changeset/lucky-pandas-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@easypost/easy-ui": minor
---

update React Aria packages to latest

React Aria consolidated its individual `@react-aria/*` and `@react-stately/*`
packages into the `react-aria` and `react-stately` monopackages, so imports now
come from those directly. `RangeCalendar`'s `isDateUnavailable` now receives the
in-progress range's anchor date as a second argument.
13 changes: 13 additions & 0 deletions .changeset/quiet-moons-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@easypost/easy-ui": patch
---

fix global style leak from CustomerPortalLayout action buttons

`CustomerPortalLayoutActions` styled its hover and focus states with bare
`[data-hovered="true"]` and `[data-focus-visible="true"]` selectors. CSS Modules
only scope class names, so those rules shipped unscoped in `style.css` and
applied a grey background and focus ring to *any* React Aria element in the
document — most visibly the `MultiSelect` input and its dropdown options. The
selectors are now scoped to the component's own button, matching
`ForgeLayoutActions`.
18 changes: 10 additions & 8 deletions easy-ui-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,21 @@
"test:watch": "vitest"
},
"dependencies": {
"@react-aria/overlays": "^3.31.0",
"@easypost/easy-ui-icons": "1.0.0-alpha.58",
"@easypost/easy-ui-tokens": "1.0.0-alpha.17",
"@react-aria/toast": "^3.0.9",
"@react-aria/utils": "^3.32.0",
"@react-stately/toast": "^3.1.2",
"@react-types/shared": "^3.32.1",
"@react-aria/overlays": "^3.32.1",
"@react-aria/toast": "^3.1.1",
"@react-aria/utils": "^3.34.1",
"@react-stately/list": "^3.14.1",
"@react-stately/toast": "^3.2.1",
"@react-types/grid": "^3.4.0",
"@react-types/shared": "^3.36.1",
"lodash": "^4.17.21",
"overlayscrollbars": "^2.3.0",
"overlayscrollbars-react": "^0.5.6",
"react-aria": "^3.45.0",
"react-aria-components": "^1.14.0",
"react-stately": "^3.43.0",
"react-aria": "^3.51.0",
"react-aria-components": "^1.20.0",
"react-stately": "^3.49.0",
"react-syntax-highlighter": "^15.6.1",
"react-transition-group": "^4.4.5",
"use-clipboard-copy": "^0.2.0"
Expand Down
3 changes: 1 addition & 2 deletions easy-ui-react/src/Calendar/Calendar.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from "react";
import { useLocale } from "react-aria";
import { DateValue } from "@react-types/calendar";
import { useLocale, DateValue } from "react-aria";
import { Meta, StoryObj } from "@storybook/react-vite";
import { InlineStoryDecorator } from "../utilities/storybook";
import {
Expand Down
2 changes: 1 addition & 1 deletion easy-ui-react/src/Calendar/Calendar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { vi } from "vitest";
import { UserEvent } from "@testing-library/user-event/dist/types/setup/setup";
import { screen } from "@testing-library/react";
import { CalendarDate } from "@internationalized/date";
import { DateValue } from "@react-types/calendar";
import { DateValue } from "react-aria";
import { render, userClick } from "../utilities/test";
import { Calendar } from "./Calendar";

Expand Down
3 changes: 1 addition & 2 deletions easy-ui-react/src/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from "react";
import { useCalendar, useLocale } from "react-aria";
import { useCalendar, useLocale, DateValue, MappedDateValue } from "react-aria";
import { useCalendarState } from "react-stately";
import { createCalendar } from "@internationalized/date";
import { DateValue, MappedDateValue } from "@react-types/calendar";
import { CalendarBase, CalendarBaseStateProps } from "./CalendarBase";

export type CalendarProps = CalendarBaseStateProps & {
Expand Down
5 changes: 2 additions & 3 deletions easy-ui-react/src/Calendar/CalendarBase.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React, { ReactNode, HTMLAttributes } from "react";
import { AriaButtonProps } from "react-aria";
import { AriaButtonProps, DateValue } from "react-aria";
import { VerticalStack } from "../VerticalStack";
import { Text } from "../Text";
import { CalendarState, RangeCalendarState } from "@react-stately/calendar";
import { CalendarState, RangeCalendarState } from "react-stately";
import { RefObject } from "@react-types/shared";
import { DateValue } from "@react-types/calendar";
import { CalendarHeader } from "./CalendarHeader";
import { CalendarGrid } from "./CalendarGrid";
import styles from "./Calendar.module.scss";
Expand Down
2 changes: 1 addition & 1 deletion easy-ui-react/src/Calendar/CalendarCell.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { has } from "lodash";
import { useCalendarCell, useLocale } from "react-aria";
import { CalendarState, RangeCalendarState } from "@react-stately/calendar";
import { CalendarState, RangeCalendarState } from "react-stately";
import { CalendarDate, isSameDay, getDayOfWeek } from "@internationalized/date";
import { Text } from "../Text";
import { classNames } from "../utilities/css";
Expand Down
2 changes: 1 addition & 1 deletion easy-ui-react/src/Calendar/CalendarGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { useCalendarGrid, useLocale } from "react-aria";
import { getWeeksInMonth } from "@internationalized/date";
import { CalendarState, RangeCalendarState } from "@react-stately/calendar";
import { CalendarState, RangeCalendarState } from "react-stately";
import { CalendarDate, isSameMonth } from "@internationalized/date";
import { Text } from "../Text";
import { CalendarCell } from "./CalendarCell";
Expand Down
6 changes: 2 additions & 4 deletions easy-ui-react/src/Calendar/CalendarHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import React, { AriaAttributes } from "react";
import { CalendarState, RangeCalendarState } from "@react-stately/calendar";
import { useDateFormatter } from "@react-aria/i18n";
import { AriaButtonProps } from "react-aria";
import { CalendarState, RangeCalendarState } from "react-stately";
import { AriaButtonProps, useDateFormatter, VisuallyHidden } from "react-aria";
import { Text } from "../Text";
import { Icon } from "../Icon";
import { HorizontalStack } from "../HorizontalStack";
import DoubleArrowLeftIcon from "@easypost/easy-ui-icons/KeyboardDoubleArrowLeft";
import DoubleArrowRightIcon from "@easypost/easy-ui-icons/KeyboardDoubleArrowRight";
import { VisuallyHidden } from "@react-aria/visually-hidden";
import { UnstyledButton } from "../UnstyledButton";

import styles from "./CalendarHeader.module.scss";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
}

.focused,
[data-focus-visible="true"] {
.button[data-focus-visible="true"] {
@include native-focus-ring;
}

.hovered,
[data-hovered="true"] {
.button[data-hovered="true"] {
background-color: design-token("color.neutral.050");
}

Expand Down
3 changes: 1 addition & 2 deletions easy-ui-react/src/DatePicker/DateField.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from "react";
import { useDateField, useDateSegment, useLocale } from "react-aria";
import { useDateField, useDateSegment, useLocale, DateValue } from "react-aria";
import {
useDateFieldState,
DateFieldState,
DateSegment as DateSegmentType,
} from "react-stately";
import { createCalendar } from "@internationalized/date";
import { DateValue } from "@react-types/calendar";
import { HorizontalStack } from "../HorizontalStack";
import { classNames } from "../utilities/css";

Expand Down
3 changes: 1 addition & 2 deletions easy-ui-react/src/DatePicker/DatePicker.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import React from "react";
import { Meta, StoryObj } from "@storybook/react-vite";
import { useLocale } from "react-aria";
import { useLocale, DateValue, MappedDateValue } from "react-aria";
import {
today,
getLocalTimeZone,
isWeekend,
endOfWeek,
} from "@internationalized/date";
import { DateValue, MappedDateValue } from "@react-types/calendar";
import { InputDecorator } from "../utilities/storybook";
import { DatePicker, DatePickerProps } from "./DatePicker";

Expand Down
2 changes: 1 addition & 1 deletion easy-ui-react/src/DatePicker/DatePicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
today,
getLocalTimeZone,
} from "@internationalized/date";
import { DateValue } from "@react-types/calendar";
import { DateValue } from "react-aria";
import { render } from "../utilities/test";
import { DatePicker } from "./DatePicker";
import { clickElement } from "../RangeCalendar/RangeCalendar.test";
Expand Down
3 changes: 1 addition & 2 deletions easy-ui-react/src/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { ReactNode } from "react";
import { useDatePicker } from "react-aria";
import { useDatePicker, DateValue, MappedDateValue } from "react-aria";
import { useDatePickerState } from "react-stately";
import { DateValue, MappedDateValue } from "@react-types/calendar";
import { DatePickerBase } from "./DatePickerBase";
import { Calendar } from "../Calendar";

Expand Down
2 changes: 1 addition & 1 deletion easy-ui-react/src/DatePicker/DatePickerBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import {
AriaButtonProps,
AriaDatePickerProps,
AriaDialogProps,
DateValue,
} from "react-aria";
import { DatePickerState, DateRangePickerState } from "react-stately";
import { DateValue } from "@react-types/calendar";
import { FocusableElement, GroupDOMAttributes } from "@react-types/shared";
import { DatePickerTrigger } from "./DatePickerTrigger";
import { DatePickerOverlay } from "./DatePickerOverlay";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { Meta, StoryObj } from "@storybook/react-vite";
import { today, getLocalTimeZone } from "@internationalized/date";
import { DateRange } from "@react-types/calendar";
import { DateRange } from "react-aria";
import { InputDecorator } from "../utilities/storybook";
import { DateRangePicker, DateRangePickerProps } from "./DateRangePicker";

Expand Down Expand Up @@ -56,7 +56,7 @@ export const DatesAvailability: Story = {

export const ControlledSelection: Story = {
render: () => {
const [date, setDate] = React.useState<DateRange>();
const [date, setDate] = React.useState<DateRange | null>(null);
return (
<DateRangePicker
value={date}
Expand All @@ -69,7 +69,7 @@ export const ControlledSelection: Story = {

export const InvalidSelection: Story = {
render: () => {
const [date, setDate] = React.useState<DateRange>({
const [date, setDate] = React.useState<DateRange | null>({
start: today(getLocalTimeZone()).subtract({ days: 7 }),
end: today(getLocalTimeZone()),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
today,
getLocalTimeZone,
} from "@internationalized/date";
import { DateValue } from "@react-types/calendar";
import { DateValue } from "react-aria";
import { render } from "../utilities/test";
import { DateRangePicker } from "./DateRangePicker";
import { clickElement } from "../RangeCalendar/RangeCalendar.test";
Expand Down
3 changes: 1 addition & 2 deletions easy-ui-react/src/DateRangePicker/DateRangePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React, { ReactNode } from "react";
import { useDateRangePicker } from "react-aria";
import { useDateRangePicker, DateValue, MappedDateValue } from "react-aria";
import { useDateRangePickerState } from "react-stately";
import { RangeValue } from "@react-types/shared";
import { DateValue, MappedDateValue } from "@react-types/calendar";
import { RangeCalendar } from "../RangeCalendar";
import { DatePickerBase } from "../DatePicker/DatePickerBase";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { DateRange } from "@react-types/calendar";
import { DateRange } from "react-aria";
import { Meta, StoryObj } from "@storybook/react-vite";
import { InlineStoryDecorator } from "../utilities/storybook";
import { today, getLocalTimeZone } from "@internationalized/date";
Expand Down
2 changes: 1 addition & 1 deletion easy-ui-react/src/RangeCalendar/RangeCalendar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { vi } from "vitest";
import { UserEvent } from "@testing-library/user-event/dist/types/setup/setup";
import { screen } from "@testing-library/react";
import { CalendarDate } from "@internationalized/date";
import { DateValue } from "@react-types/calendar";
import { DateValue } from "react-aria";
import { render, userClick } from "../utilities/test";
import { RangeCalendar } from "./RangeCalendar";

Expand Down
27 changes: 23 additions & 4 deletions easy-ui-react/src/RangeCalendar/RangeCalendar.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import React from "react";
import { useRangeCalendar, useLocale } from "react-aria";
import {
useRangeCalendar,
useLocale,
DateValue,
MappedDateValue,
DateRange,
} from "react-aria";
import { useRangeCalendarState } from "react-stately";
import { RangeValue } from "@react-types/shared";
import { createCalendar } from "@internationalized/date";
import { DateValue, MappedDateValue, DateRange } from "@react-types/calendar";
import { CalendarDate, createCalendar } from "@internationalized/date";
import { CalendarBase, CalendarBaseStateProps } from "../Calendar/CalendarBase";

export type RangeCalendarProps = CalendarBaseStateProps & {
export type RangeCalendarProps = Omit<
CalendarBaseStateProps,
"isDateUnavailable"
> & {
/**
* The current value (controlled).
*/
Expand All @@ -19,6 +27,17 @@ export type RangeCalendarProps = CalendarBaseStateProps & {
* Handler that is called when the value changes.
*/
onChange?: (value: RangeValue<MappedDateValue<DateValue>>) => void;
/**
* Callback that is called for each date of the calendar. If
* it returns true, then the date is unavailable.
*
* `anchorDate` is the date the in-progress range is anchored to, or `null`
* when no range is being selected.
*/
isDateUnavailable?: (
date: DateValue,
anchorDate: CalendarDate | null,
) => boolean;
};

/**
Expand Down
11 changes: 9 additions & 2 deletions easy-ui-react/src/TabPanels/TabPanelsTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,15 @@ export function TabPanelsTabs(props: TabPanelsTabsProps) {
const { tabProps, setTabListState } = useTabPanels();
const ref = React.useRef(null);
const mergedProps = mergeProps(tabProps, props);
const state = useTabListState(mergedProps);
const { tabListProps } = useTabList(mergedProps, state, ref);
// react-aria narrowed `selectedKey` to `Key | undefined`. Our public API
// accepts `null` to mean "no selection", which react-aria now spells as
// `undefined`.
const listProps = {
...mergedProps,
selectedKey: mergedProps.selectedKey ?? undefined,
};
const state = useTabListState(listProps);
const { tabListProps } = useTabList(listProps, state, ref);

useEffect(
() => {
Expand Down
9 changes: 7 additions & 2 deletions easy-ui-react/src/utilities/useScrollbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ export function useScrollbar(
defer: false,
});
useEffect(() => {
if (scrollRef.current) {
initialize({ target: scrollRef.current });
const el = scrollRef.current;
// React Aria builds collections by rendering children into a detached
// fragment owned by an inert document. Elements there have no
// `defaultView`, which OverlayScrollbars dereferences, so skip those
// passes and wait for the render into the live document.
if (el && el.ownerDocument.defaultView) {
initialize({ target: el });
}
}, [initialize, scrollRef]);
}
Loading
Loading