36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import type { HTMLAttributes, ReactNode } from "react";
|
||
|
|
import { I18nProvider, useLocale } from "react-aria-components";
|
||
|
|
import { cx } from "@/utils/cx";
|
||
|
|
|
||
|
|
export type Direction = "ltr" | "rtl";
|
||
|
|
|
||
|
|
export interface DirectionProviderProps extends Omit<HTMLAttributes<HTMLDivElement>, "dir" | "lang" | "children"> {
|
||
|
|
/** BCP 47 language tag. Arabic and Hebrew resolve to RTL; Chinese to LTR. */
|
||
|
|
locale: string;
|
||
|
|
children: ReactNode;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Keeps CSS direction, React Aria keyboard behavior and portalled menus in sync.
|
||
|
|
* Use at the app root, or nest providers for regions in another language.
|
||
|
|
* The default display: contents boundary preserves the surrounding layout.
|
||
|
|
*/
|
||
|
|
export function DirectionProvider({ locale, ...props }: DirectionProviderProps) {
|
||
|
|
return (
|
||
|
|
<I18nProvider locale={locale}>
|
||
|
|
<DirectionBoundary {...props} />
|
||
|
|
</I18nProvider>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
function DirectionBoundary({ children, className, ...props }: Omit<DirectionProviderProps, "locale">) {
|
||
|
|
const { locale, direction } = useLocale();
|
||
|
|
return <div {...props} lang={locale} dir={direction} className={cx("contents", className)}>{children}</div>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Also works inside a React Aria I18nProvider. */
|
||
|
|
export function useDirection(): Direction {
|
||
|
|
return useLocale().direction;
|
||
|
|
}
|