Skip to content

Commit

Permalink
[core] Make context definitions consistent (mui#735)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaldudak authored Oct 17, 2024
1 parent 7445aad commit 8c52af4
Show file tree
Hide file tree
Showing 71 changed files with 368 additions and 226 deletions.
4 changes: 2 additions & 2 deletions docs/app/experiments/slider-marks.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';
import * as React from 'react';
import { Slider } from '@base_ui/react/Slider';
import { useSliderContext } from '../../../packages/mui-base/src/Slider/Root/SliderContext';
import { useSliderRootContext } from '../../../packages/mui-base/src/Slider/Root/SliderRootContext';

const STOPS = [
{
Expand Down Expand Up @@ -33,7 +33,7 @@ function getSliderThumbAriaValueText(value: number) {
// for "inverted track", the track/rail can be styled with CSS but a prop is needed to flip the "mark active" state
function MarkWithLabel(props: { index: number; value: number; label: string; inverted?: boolean }) {
const { index, value, label, inverted = false } = props;
const { direction, values } = useSliderContext();
const { direction, values } = useSliderRootContext();
const isRtl = direction === 'rtl';
const isFilled = inverted ? value >= values[0] : values[0] >= value;
return (
Expand Down
4 changes: 2 additions & 2 deletions docs/app/experiments/slider-tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as React from 'react';
import { useTheme } from '@mui/system';
import { Slider } from '@base_ui/react/Slider';
import { Tooltip } from '@base_ui/react/Tooltip';
import { useSliderContext } from '../../../packages/mui-base/src/Slider/Root/SliderContext';
import { useSliderRootContext } from '../../../packages/mui-base/src/Slider/Root/SliderRootContext';

function useIsDarkMode() {
const theme = useTheme();
Expand Down Expand Up @@ -74,7 +74,7 @@ export default function App() {

const SliderMark = React.forwardRef(function SliderMark(props: any, ref: React.ForwardedRef<any>) {
const { index, style, ...otherProps } = props;
const { percentageValues } = useSliderContext();
const { percentageValues } = useSliderRootContext();
const isFilled = percentageValues[0] >= index * 10;
return (
<span
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@ export const AlertDialogRootContext = React.createContext<AlertDialogRootContext
undefined,
);

if (process.env.NODE_ENV !== 'production') {
AlertDialogRootContext.displayName = 'AlertDialogRootContext';
}

export function useAlertDialogRootContext() {
const context = React.useContext(AlertDialogRootContext);
if (context === undefined) {
throw new Error('useAlertDialogRootContext must be used within an AlertDialogRoot');
throw new Error(
'Base UI: AlertDialogRootContext is missing. AlertDialog parts must be placed within <AlertDialog.Root>.',
);
}

return context;
}
11 changes: 8 additions & 3 deletions packages/mui-base/src/Checkbox/Root/CheckboxRootContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ import type { CheckboxRoot } from './CheckboxRoot';

export type CheckboxRootContext = CheckboxRoot.OwnerState;

export const CheckboxRootContext = React.createContext<CheckboxRootContext | null>(null);
export const CheckboxRootContext = React.createContext<CheckboxRootContext | undefined>(undefined);

if (process.env.NODE_ENV !== 'production') {
CheckboxRootContext.displayName = 'CheckboxRootContext';
}

export function useCheckboxRootContext() {
const context = React.useContext(CheckboxRootContext);
if (context === null) {
if (context === undefined) {
throw new Error(
'Base UI: Checkbox.Indicator must be placed inside the Checkbox.Root component.',
'Base UI: CheckboxRootContext is missing. Checkbox parts must be placed within <Checkbox.Root>.',
);
}

return context;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,21 @@ export interface CheckboxGroupRootContext {
parent: UseCheckboxGroupParent.ReturnValue;
}

export const CheckboxGroupRootContext = React.createContext<CheckboxGroupRootContext | null>(null);
export const CheckboxGroupRootContext = React.createContext<CheckboxGroupRootContext | undefined>(
undefined,
);

if (process.env.NODE_ENV !== 'production') {
CheckboxGroupRootContext.displayName = 'CheckboxGroupRootContext';
}

export function useCheckboxGroupRootContext(optional = true) {
const context = React.useContext(CheckboxGroupRootContext);
if (context === null && !optional) {
throw new Error('Base UI: CheckboxGroupRootContext is not defined.');
if (context === undefined && !optional) {
throw new Error(
'Base UI: CheckboxGroupRootContext is missing. CheckboxGroup parts must be placed within <CheckboxGroup.Root>.',
);
}

return context;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as React from 'react';
import { createRenderer } from '@mui/internal-test-utils';
import { Collapsible } from '@base_ui/react/Collapsible';
import { CollapsibleContext } from '../Root/CollapsibleContext';
import { describeConformance } from '../../../test/describeConformance';
import { CollapsibleRootContext } from '../Root/CollapsibleRootContext';

const contextValue: Collapsible.Root.Context = {
const contextValue: CollapsibleRootContext = {
animated: false,
contentId: 'ContentId',
disabled: false,
Expand All @@ -28,7 +28,9 @@ describe('<Collapsible.Content />', () => {
inheritComponent: 'div',
render: (node) => {
const { container, ...other } = render(
<CollapsibleContext.Provider value={contextValue}>{node}</CollapsibleContext.Provider>,
<CollapsibleRootContext.Provider value={contextValue}>
{node}
</CollapsibleRootContext.Provider>,
);

return { container, ...other };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import { BaseUIComponentProps } from '../../utils/types';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { useCollapsibleContext } from '../Root/CollapsibleContext';
import { useCollapsibleContext } from '../Root/CollapsibleRootContext';
import type { CollapsibleRoot } from '../Root/CollapsibleRoot';
import { collapsibleStyleHookMapping } from '../Root/styleHooks';
import { useCollapsibleContent } from './useCollapsibleContent';
Expand Down
22 changes: 0 additions & 22 deletions packages/mui-base/src/Collapsible/Root/CollapsibleContext.tsx

This file was deleted.

16 changes: 7 additions & 9 deletions packages/mui-base/src/Collapsible/Root/CollapsibleRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import { BaseUIComponentProps } from '../../utils/types';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { useCollapsibleRoot } from './useCollapsibleRoot';
import { CollapsibleContext } from './CollapsibleContext';
import { CollapsibleRootContext } from './CollapsibleRootContext';
import { collapsibleStyleHookMapping } from './styleHooks';

/**
Expand Down Expand Up @@ -50,7 +50,7 @@ const CollapsibleRoot = React.forwardRef(function CollapsibleRoot(
[collapsible.open, collapsible.disabled, collapsible.transitionStatus],
);

const contextValue: CollapsibleRoot.Context = React.useMemo(
const contextValue: CollapsibleRootContext = React.useMemo(
() => ({
...collapsible,
ownerState,
Expand All @@ -69,24 +69,22 @@ const CollapsibleRoot = React.forwardRef(function CollapsibleRoot(

if (!renderProp) {
return (
<CollapsibleContext.Provider value={contextValue}>{children}</CollapsibleContext.Provider>
<CollapsibleRootContext.Provider value={contextValue}>
{children}
</CollapsibleRootContext.Provider>
);
}

return (
<CollapsibleContext.Provider value={contextValue}>
<CollapsibleRootContext.Provider value={contextValue}>
{renderElement()}
</CollapsibleContext.Provider>
</CollapsibleRootContext.Provider>
);
});

export { CollapsibleRoot };

export namespace CollapsibleRoot {
export interface Context extends useCollapsibleRoot.ReturnValue {
ownerState: OwnerState;
}

export interface OwnerState
extends Pick<useCollapsibleRoot.ReturnValue, 'open' | 'disabled' | 'transitionStatus'> {}

Expand Down
27 changes: 27 additions & 0 deletions packages/mui-base/src/Collapsible/Root/CollapsibleRootContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use client';
import * as React from 'react';
import type { CollapsibleRoot } from './CollapsibleRoot';
import type { useCollapsibleRoot } from './useCollapsibleRoot';

export interface CollapsibleRootContext extends useCollapsibleRoot.ReturnValue {
ownerState: CollapsibleRoot.OwnerState;
}

export const CollapsibleRootContext = React.createContext<CollapsibleRootContext | undefined>(
undefined,
);

if (process.env.NODE_ENV !== 'production') {
CollapsibleRootContext.displayName = 'CollapsibleRootContext';
}

export function useCollapsibleContext() {
const context = React.useContext(CollapsibleRootContext);
if (context === undefined) {
throw new Error(
'Base UI: CollapsibleRootContext is missing. Collapsible parts must be placed within <Collapsible.Root>.',
);
}

return context;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as React from 'react';
import { createRenderer } from '@mui/internal-test-utils';
import { Collapsible } from '@base_ui/react/Collapsible';
import { CollapsibleContext } from '../Root/CollapsibleContext';
import { describeConformance } from '../../../test/describeConformance';
import { CollapsibleRootContext } from '../Root/CollapsibleRootContext';

const contextValue: Collapsible.Root.Context = {
const contextValue: CollapsibleRootContext = {
animated: false,
contentId: 'ContentId',
disabled: false,
Expand All @@ -28,7 +28,9 @@ describe('<Collapsible.Trigger />', () => {
inheritComponent: 'button',
render: (node) => {
const { container, ...other } = render(
<CollapsibleContext.Provider value={contextValue}>{node}</CollapsibleContext.Provider>,
<CollapsibleRootContext.Provider value={contextValue}>
{node}
</CollapsibleRootContext.Provider>,
);

return { container, ...other };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { BaseUIComponentProps } from '../../utils/types';
import { useCollapsibleContext } from '../Root/CollapsibleContext';
import { useCollapsibleContext } from '../Root/CollapsibleRootContext';
import { CollapsibleRoot } from '../Root/CollapsibleRoot';
import { collapsibleStyleHookMapping } from '../Root/styleHooks';
import { useCollapsibleTrigger } from './useCollapsibleTrigger';
Expand Down
4 changes: 4 additions & 0 deletions packages/mui-base/src/Composite/List/CompositeListContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export const CompositeListContext = React.createContext<CompositeListContextValu
elementsRef: { current: [] },
});

if (process.env.NODE_ENV !== 'production') {
CompositeListContext.displayName = 'CompositeListContext';
}

export function useCompositeListContext() {
return React.useContext(CompositeListContext);
}
2 changes: 1 addition & 1 deletion packages/mui-base/src/Composite/Root/CompositeRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const CompositeRoot = React.forwardRef(function CompositeRoot(
extraProps: otherProps,
});

const contextValue: CompositeRootContext.Value = React.useMemo(
const contextValue: CompositeRootContext = React.useMemo(
() => ({ activeIndex, onActiveIndexChange }),
[activeIndex, onActiveIndexChange],
);
Expand Down
27 changes: 17 additions & 10 deletions packages/mui-base/src/Composite/Root/CompositeRootContext.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
'use client';
import * as React from 'react';

export const CompositeRootContext = React.createContext<CompositeRootContext.Value | null>(null);
export interface CompositeRootContext {
activeIndex: number;
onActiveIndexChange: (index: number) => void;
}

export const CompositeRootContext = React.createContext<CompositeRootContext | undefined>(
undefined,
);

if (process.env.NODE_ENV !== 'production') {
CompositeRootContext.displayName = 'CompositeRootContext';
}

export function useCompositeRootContext() {
const context = React.useContext(CompositeRootContext);
if (context === null) {
throw new Error('<Composite.Item> must be used within <Composite.Root>');
if (context === undefined) {
throw new Error(
'Base UI: CompositeRootContext is missing. Composite parts must be placed within <Composite.Root>.',
);
}
return context;
}

export namespace CompositeRootContext {
export interface Value {
activeIndex: number;
onActiveIndexChange: (index: number) => void;
}
return context;
}
5 changes: 4 additions & 1 deletion packages/mui-base/src/Dialog/Root/DialogRootContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ export const DialogRootContext = React.createContext<DialogRootContext | undefin
export function useDialogRootContext() {
const context = React.useContext(DialogRootContext);
if (context === undefined) {
throw new Error('useDialogRootContext must be used within a DialogRoot');
throw new Error(
'Base UI: DialogRootContext is missing. Dialog parts must be placed within <Dialog.Root>.',
);
}

return context;
}
4 changes: 3 additions & 1 deletion packages/mui-base/src/Field/Root/FieldRootContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ export function useFieldRootContext(optional = true) {
const context = React.useContext(FieldRootContext);

if (context.setControlId === NOOP && !optional) {
throw new Error('Base UI: Field components must be placed within <Field.Root>.');
throw new Error(
'Base UI: FieldRootContext is missing. Field parts must be placed within <Field.Root>.',
);
}

return context;
Expand Down
4 changes: 4 additions & 0 deletions packages/mui-base/src/Form/Root/FormRootContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export const FormRootContext = React.createContext<FormRootContext>({
onClearErrors: () => {},
});

if (process.env.NODE_ENV !== 'production') {
FormRootContext.displayName = 'FormRootContext';
}

export function useFormRootContext() {
return React.useContext(FormRootContext);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const testRootContext: MenuRootContext = {
getPositionerProps: (p) => ({ ...p }),
getTriggerProps: (p) => ({ ...p }),
getItemProps: (p) => ({ ...p }),
parentContext: null,
parentContext: undefined,
nested: false,
triggerElement: null,
setTriggerElement: () => {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ export const MenuCheckboxItemContext = React.createContext<MenuCheckboxItemConte
export function useMenuCheckboxItemContext() {
const context = React.useContext(MenuCheckboxItemContext);
if (context === undefined) {
throw new Error('useMenuCheckboxItemContext must be used within a MenuCheckboxItemProvider');
throw new Error(
'Base UI: MenuCheckboxItemContext is missing. MenuCheckboxItem parts must be placed within <Menu.CheckboxItem>.',
);
}

return context;
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/Menu/Group/MenuGroupContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ if (process.env.NODE_ENV !== 'production') {

export function useMenuGroupRootContext() {
const context = React.useContext(MenuGroupContext);
if (context == null) {
if (context === undefined) {
throw new Error('Base UI: Missing MenuGroupRootContext provider');
}

Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/Menu/Item/MenuItem.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const testRootContext: MenuRootContext = {
getPositionerProps: (p) => ({ ...p }),
getTriggerProps: (p) => ({ ...p }),
getItemProps: (p) => ({ ...p }),
parentContext: null,
parentContext: undefined,
nested: false,
triggerElement: null,
setTriggerElement: () => {},
Expand Down
Loading

0 comments on commit 8c52af4

Please sign in to comment.