Skip to content
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

[core] Make context definitions consistent #735

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
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
Expand Up @@ -3,8 +3,9 @@ import { createRenderer } from '@mui/internal-test-utils';
import * as Collapsible from '@base_ui/react/Collapsible';
import { CollapsibleContext } from '@base_ui/react/Collapsible';
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 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
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
Expand Up @@ -3,8 +3,9 @@ import { createRenderer } from '@mui/internal-test-utils';
import * as Collapsible from '@base_ui/react/Collapsible';
import { CollapsibleContext } from '@base_ui/react/Collapsible';
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 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
5 changes: 4 additions & 1 deletion packages/mui-base/src/Collapsible/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export { CollapsibleRoot as Root } from './Root/CollapsibleRoot';
export { useCollapsibleRoot } from './Root/useCollapsibleRoot';
export { CollapsibleContext, useCollapsibleContext } from './Root/CollapsibleContext';
export {
CollapsibleRootContext as CollapsibleContext,
useCollapsibleContext,
} from './Root/CollapsibleRootContext';

export { CollapsibleTrigger as Trigger } from './Trigger/CollapsibleTrigger';
export { useCollapsibleTrigger } from './Trigger/useCollapsibleTrigger';
Expand Down
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
2 changes: 1 addition & 1 deletion packages/mui-base/src/Menu/Popup/MenuPopup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,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 @@ -12,7 +12,7 @@ const testRootContext: MenuRootContext = {
getPositionerProps: (p) => ({ ...p }),
getTriggerProps: (p) => ({ ...p }),
getItemProps: (p) => ({ ...p }),
parentContext: null,
parentContext: undefined,
nested: false,
triggerElement: null,
setTriggerElement: () => {},
Expand Down
10 changes: 7 additions & 3 deletions packages/mui-base/src/Menu/Positioner/MenuPositionerContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,20 @@ export interface MenuPositionerContext {
arrowStyles: React.CSSProperties;
}

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

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

export function useMenuPositionerContext() {
const context = React.useContext(MenuPositionerContext);
if (context === null) {
throw new Error('<Menu.Popup> must be used within the <Menu.Positioner> component');
if (context === undefined) {
throw new Error(
'Base UI: MenuPositionerContext is missing. MenuPositioner parts must be placed within <Menu.Positioner>.',
);
}
return context;
}
Loading
Loading