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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "test: add SplitButton regression coverage for default menu icon and slot element metadata",
"packageName": "@fluentui/react-button",
"email": "vgenaev@gmail.com",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat(react-color-picker): expose headless base APIs",
"packageName": "@fluentui/react-color-picker",
"email": "dmytrokirpa@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "feat: add color picker controls",
"packageName": "@fluentui/react-headless-components-preview",
"email": "dmytrokirpa@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "feat: add headless CompoundButton",
"packageName": "@fluentui/react-headless-components-preview",
"email": "vgenaev@gmail.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import { renderHook } from '@testing-library/react-hooks';
import userEvent from '@testing-library/user-event';
import { isSlot, SLOT_ELEMENT_TYPE_SYMBOL } from '@fluentui/react-utilities';
import { isConformant } from '../../testing/isConformant';
import { SplitButton } from './SplitButton';
import { Button } from '../Button/Button';
import { MenuButton } from '../MenuButton/MenuButton';
import { useSplitButton_unstable } from './useSplitButton';
import type { SplitButtonProps } from './SplitButton.types';

describe('SplitButton', () => {
Expand Down Expand Up @@ -176,4 +181,35 @@ describe('SplitButton', () => {
userEvent.click(primaryActionButton);
expect(onClick).not.toHaveBeenCalled();
});

it('renders the default styled menu icon (chevron) when no menu icon is provided', () => {
const { getAllByRole } = render(<SplitButton>This is a button</SplitButton>);
const [, menuButton] = getAllByRole('button');

expect(menuButton.querySelector('svg')).toBeTruthy();
});

it('renders an explicit menu icon instead of the default chevron', () => {
const { getAllByRole, getByText } = render(<SplitButton menuIcon="Test MenuIcon">This is a button</SplitButton>);
const [, menuButton] = getAllByRole('button');

expect(getByText('Test MenuIcon')).toBeTruthy();
expect(menuButton.querySelector('svg')).toBeFalsy();
});

it('resolves child slot element metadata to the styled Button and MenuButton components', () => {
const { result } = renderHook(() => useSplitButton_unstable({ children: 'This is a button' }, React.createRef()));

const { primaryActionButton, menuButton } = result.current;

expect(isSlot(primaryActionButton)).toBe(true);
expect(isSlot(menuButton)).toBe(true);

if (!isSlot(primaryActionButton) || !isSlot(menuButton)) {
return;
}

expect(primaryActionButton[SLOT_ELEMENT_TYPE_SYMBOL]).toBe(Button);
expect(menuButton[SLOT_ELEMENT_TYPE_SYMBOL]).toBe(MenuButton);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import type { ComponentProps } from '@fluentui/react-utilities';
import type { ComponentState } from '@fluentui/react-utilities';
import type { ContextSelector } from '@fluentui/react-context-selector';
import type { EventData } from '@fluentui/react-utilities';
import type { EventHandler } from '@fluentui/react-utilities';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
Expand All @@ -17,6 +18,12 @@ import type { SlotClassNames } from '@fluentui/react-utilities';
// @public
export const AlphaSlider: ForwardRefComponent<AlphaSliderProps>;

// @public
export type AlphaSliderBaseProps = Omit<AlphaSliderProps, 'shape'>;

// @public
export type AlphaSliderBaseState = Omit<AlphaSliderState, 'shape'>;

// @public (undocumented)
export const alphaSliderClassNames: SlotClassNames<AlphaSliderSlots>;

Expand All @@ -34,6 +41,12 @@ export type AlphaSliderState = ComponentState<AlphaSliderSlots> & Pick<AlphaSlid
// @public
export const ColorArea: ForwardRefComponent<ColorAreaProps>;

// @public
export type ColorAreaBaseProps = Omit<ColorAreaProps, 'shape'>;

// @public
export type ColorAreaBaseState = ComponentState<Required<ColorAreaSlots>> & Pick<ColorAreaProps, 'color'>;

// @public (undocumented)
export const colorAreaClassNames: SlotClassNames<ColorAreaSlots>;

Expand All @@ -55,12 +68,33 @@ export type ColorAreaSlots = {
// @public
export type ColorAreaState = ComponentState<Required<ColorAreaSlots>> & Pick<ColorAreaProps, 'color' | 'shape'>;

// @public (undocumented)
export type ColorChannel = 'hue' | 'saturation' | 'value';

// @public
export const ColorPicker: ForwardRefComponent<ColorPickerProps>;

// @public
export type ColorPickerBaseProps = Omit<ColorPickerProps, 'shape'>;

// @public
export type ColorPickerBaseState = Omit<ColorPickerState, 'shape'>;

// @public (undocumented)
export const colorPickerClassNames: SlotClassNames<ColorPickerSlots>;

// @public
export type ColorPickerContextValue = Pick<ColorPickerProps, 'shape' | 'color'> & {
requestChange: (event: React_2.ChangeEvent<HTMLInputElement>, data: {
color: HsvColor;
}) => void;
};

// @public (undocumented)
export type ColorPickerContextValues = {
colorPicker: ColorPickerContextValue;
};

// @public
export type ColorPickerProps = Omit<ComponentProps<Partial<ColorPickerSlots>>, 'color'> & {
color?: HsvColor;
Expand All @@ -79,6 +113,12 @@ export type ColorPickerState = ComponentState<ColorPickerSlots> & ColorPickerCon
// @public
export const ColorSlider: ForwardRefComponent<ColorSliderProps>;

// @public (undocumented)
export type ColorSliderBaseProps = Omit<ColorSliderProps, 'shape'>;

// @public (undocumented)
export type ColorSliderBaseState = Omit<ColorSliderState, 'shape'>;

// @public (undocumented)
export const colorSliderClassNames: SlotClassNames<ColorSliderSlots>;

Expand All @@ -103,38 +143,56 @@ export type ColorSliderSlots = {
export type ColorSliderState = ComponentState<ColorSliderSlots> & Pick<ColorSliderProps, 'vertical' | 'shape' | 'channel'>;

// @public
export const renderAlphaSlider_unstable: (state: AlphaSliderState) => JSXElement;
export const renderAlphaSlider_unstable: (state: AlphaSliderBaseState) => JSXElement;

// @public
export const renderColorArea_unstable: (state: ColorAreaState) => JSXElement;
export const renderColorArea_unstable: (state: ColorAreaBaseState) => JSXElement;

// @public
export const renderColorPicker_unstable: (state: ColorPickerState, contextValues: ColorPickerContextValues) => JSXElement;
export const renderColorPicker_unstable: (state: ColorPickerBaseState, contextValues: ColorPickerContextValues) => JSXElement;

// @public
export const renderColorSlider_unstable: (state: ColorSliderState) => JSXElement;
export const renderColorSlider_unstable: (state: ColorSliderBaseState) => JSXElement;

// @public
export const useAlphaSlider_unstable: (props: AlphaSliderProps, ref: React_2.Ref<HTMLInputElement>) => AlphaSliderState;

// @public (undocumented)
export const useAlphaSliderBase_unstable: (props: AlphaSliderBaseProps, ref: React_2.Ref<HTMLInputElement>) => AlphaSliderBaseState;

// @public
export const useAlphaSliderStyles_unstable: (state: AlphaSliderState) => AlphaSliderState;

// @public
export const useColorArea_unstable: (props: ColorAreaProps, ref: React_2.Ref<HTMLDivElement>) => ColorAreaState;

// @public
export const useColorAreaStyles_unstable: (state: ColorAreaState) => ColorAreaState;
export const useColorAreaBase_unstable: (props: ColorAreaBaseProps, ref: React_2.Ref<HTMLDivElement>) => ColorAreaBaseState;

// @public
export const useColorAreaStyles_unstable: (state: ColorAreaState) => ColorAreaState;

// @public (undocumented)
export const useColorPicker_unstable: (props: ColorPickerProps, ref: React_2.Ref<HTMLDivElement>) => ColorPickerState;

// @public
export const useColorPickerBase_unstable: (props: ColorPickerBaseProps, ref: React_2.Ref<HTMLDivElement>) => ColorPickerBaseState;

// @public (undocumented)
export const useColorPickerContextValue_unstable: <T>(selector: ContextSelector<ColorPickerContextValue, T>) => T;

// @public (undocumented)
export const useColorPickerContextValues: (state: ColorPickerState) => ColorPickerContextValues;

// @public
export const useColorPickerStyles_unstable: (state: ColorPickerState) => ColorPickerState;

// @public
export const useColorSlider_unstable: (props: ColorSliderProps, ref: React_2.Ref<HTMLInputElement>) => ColorSliderState;

// @public
export const useColorSliderBase_unstable: (props: ColorSliderBaseProps, ref: React_2.Ref<HTMLInputElement>) => ColorSliderBaseState;

// @public
export const useColorSliderStyles_unstable: (state: ColorSliderState) => ColorSliderState;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
export type { AlphaSliderProps, AlphaSliderSlots, AlphaSliderState } from './components/AlphaSlider/index';
export type {
AlphaSliderBaseProps,
AlphaSliderBaseState,
AlphaSliderProps,
AlphaSliderSlots,
AlphaSliderState,
} from './components/AlphaSlider/index';
export {
AlphaSlider,
alphaSliderCSSVars,
alphaSliderClassNames,
renderAlphaSlider_unstable,
useAlphaSliderBase_unstable,
useAlphaSliderStyles_unstable,
useAlphaSlider_unstable,
} from './components/AlphaSlider/index';
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export type {
ColorAreaBaseProps,
ColorAreaBaseState,
ColorAreaOnColorChangeData,
ColorAreaProps,
ColorAreaSlots,
Expand All @@ -9,6 +11,7 @@ export {
colorAreaCSSVars,
colorAreaClassNames,
renderColorArea_unstable,
useColorAreaBase_unstable,
useColorAreaStyles_unstable,
useColorArea_unstable,
} from './components/ColorArea/index';
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export type {
ColorPickerBaseProps,
ColorPickerBaseState,
ColorPickerOnChangeData,
ColorPickerProps,
ColorPickerSlots,
Expand All @@ -8,6 +10,9 @@ export {
ColorPicker,
colorPickerClassNames,
renderColorPicker_unstable,
useColorPickerBaseContextValues_unstable,
useColorPickerBase_unstable,
useColorPickerContextValues,
useColorPickerStyles_unstable,
useColorPicker_unstable,
} from './components/ColorPicker/index';
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export type {
ColorChannel,
ColorSliderBaseProps,
ColorSliderBaseState,
ColorSliderProps,
ColorSliderSlots,
ColorSliderState,
Expand All @@ -9,6 +12,7 @@ export {
colorSliderCSSVars,
colorSliderClassNames,
renderColorSlider_unstable,
useColorSliderBase_unstable,
useColorSliderStyles_unstable,
useColorSlider_unstable,
} from './components/ColorSlider/index';
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,19 @@ export type AlphaSliderProps = Omit<ColorSliderProps, 'channel'> & {
transparency?: boolean;
};

/**
* AlphaSlider Base Props
*/
export type AlphaSliderBaseProps = Omit<AlphaSliderProps, 'shape'>;

/**
* State used in rendering AlphaSlider
*/
export type AlphaSliderState = ComponentState<AlphaSliderSlots> &
Pick<AlphaSliderProps, 'vertical'> &
Omit<ColorSliderState, keyof ColorSliderSlots | 'components'>;

/**
* State used in rendering unstyled AlphaSlider
*/
export type AlphaSliderBaseState = Omit<AlphaSliderState, 'shape'>;
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
export { AlphaSlider } from './AlphaSlider';
export type { AlphaSliderProps, AlphaSliderSlots, AlphaSliderState } from './AlphaSlider.types';
export type {
AlphaSliderBaseProps,
AlphaSliderBaseState,
AlphaSliderProps,
AlphaSliderSlots,
AlphaSliderState,
} from './AlphaSlider.types';
export { renderAlphaSlider_unstable } from './renderAlphaSlider';
export { useAlphaSlider_unstable } from './useAlphaSlider';
export { useAlphaSliderBase_unstable, useAlphaSlider_unstable } from './useAlphaSlider';
export {
alphaSliderCSSVars,
alphaSliderClassNames,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@

import { assertSlots } from '@fluentui/react-utilities';
import type { JSXElement } from '@fluentui/react-utilities';
import type { AlphaSliderState, AlphaSliderSlots } from './AlphaSlider.types';
import type { AlphaSliderBaseState, AlphaSliderSlots } from './AlphaSlider.types';

/**
* Render the final JSX of AlphaSlider
*/
export const renderAlphaSlider_unstable = (state: AlphaSliderState): JSXElement => {
export const renderAlphaSlider_unstable = (state: AlphaSliderBaseState): JSXElement => {
assertSlots<AlphaSliderSlots>(state);

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { useAlphaSlider_unstable } from './useAlphaSlider';
import { ColorPickerProvider } from '../../contexts/colorPicker';

describe('useAlphaSlider', () => {
it('uses the default shape', () => {
const ref = React.createRef<HTMLInputElement>();
const { result } = renderHook(() => useAlphaSlider_unstable({}, ref));

expect(result.current.shape).toBe('rounded');
});

it('uses the shape from context', () => {
const ref = React.createRef<HTMLInputElement>();
const { result } = renderHook(() => useAlphaSlider_unstable({}, ref), {
wrapper: ({ children }: { children: React.ReactNode }) => (
<ColorPickerProvider value={{ color: undefined, shape: 'square', requestChange: jest.fn() }}>
{children}
</ColorPickerProvider>
),
});

expect(result.current.shape).toBe('square');
});

it('prefers the shape prop over context', () => {
const ref = React.createRef<HTMLInputElement>();
const { result } = renderHook(() => useAlphaSlider_unstable({ shape: 'rounded' }, ref), {
wrapper: ({ children }: { children: React.ReactNode }) => (
<ColorPickerProvider value={{ color: undefined, shape: 'square', requestChange: jest.fn() }}>
{children}
</ColorPickerProvider>
),
});

expect(result.current.shape).toBe('rounded');
});

it('uses the shape prop', () => {
const ref = React.createRef<HTMLInputElement>();
const { result } = renderHook(() => useAlphaSlider_unstable({ shape: 'square' }, ref));

expect(result.current.shape).toBe('square');
});
});
Loading
Loading