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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat: add base hooks for Rating",
"packageName": "@fluentui/react-rating",
"email": "dmytrokirpa@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ import type { SlotClassNames } from '@fluentui/react-utilities';
// @public
export const Rating: ForwardRefComponent<RatingProps>;

// @public
export type RatingBaseProps = Omit<RatingProps, 'color' | 'size'>;

// @public
export type RatingBaseState = Omit<RatingState, 'color' | 'size'>;

// @public (undocumented)
export const ratingClassNames: SlotClassNames<RatingSlots>;

Expand All @@ -28,6 +34,12 @@ export type RatingContextValues = {
// @public
export const RatingDisplay: ForwardRefComponent<RatingDisplayProps>;

// @public
export type RatingDisplayBaseProps = Omit<RatingDisplayProps, 'color' | 'size'>;

// @public
export type RatingDisplayBaseState = Omit<RatingDisplayState, 'color' | 'size' | 'icon'> & Pick<RatingDisplayProps, 'icon'>;

// @public (undocumented)
export const ratingDisplayClassNames: SlotClassNames<RatingDisplaySlots>;

Expand Down Expand Up @@ -60,6 +72,12 @@ export type RatingDisplayState = ComponentState<RatingDisplaySlots> & Required<P
// @public
export const RatingItem: ForwardRefComponent<RatingItemProps>;

// @public
export type RatingItemBaseProps = RatingItemProps;

// @public
export type RatingItemBaseState = Omit<RatingItemState, 'color' | 'size'>;

// @public (undocumented)
export const ratingItemClassNames: SlotClassNames<RatingItemSlots>;

Expand Down Expand Up @@ -117,23 +135,29 @@ export type RatingState = ComponentState<RatingSlots> & Required<Pick<RatingProp
};

// @public
export const renderRating_unstable: (state: RatingState, contextValues: RatingContextValues) => JSXElement;
export const renderRating_unstable: (state: RatingBaseState, contextValues: RatingContextValues) => JSXElement;

// @public
export const renderRatingDisplay_unstable: (state: RatingDisplayState, contextValues: RatingDisplayContextValues) => JSXElement;
export const renderRatingDisplay_unstable: (state: RatingDisplayBaseState, contextValues: RatingDisplayContextValues) => JSXElement;

// @public
export const renderRatingItem_unstable: (state: RatingItemState) => JSXElement;
export const renderRatingItem_unstable: (state: RatingItemBaseState) => JSXElement;

// @public
export const useRating_unstable: (props: RatingProps, ref: React_2.Ref<HTMLDivElement>) => RatingState;

// @public
export const useRatingBase_unstable: (props: RatingBaseProps, ref: React_2.Ref<HTMLDivElement>) => RatingBaseState;

// @public (undocumented)
export const useRatingContextValues: (ratingState: RatingState) => RatingContextValues;

// @public
export const useRatingDisplay_unstable: (props: RatingDisplayProps, ref: React_2.Ref<HTMLDivElement>) => RatingDisplayState;

// @public
export const useRatingDisplayBase_unstable: (props: RatingDisplayBaseProps, ref: React_2.Ref<HTMLDivElement>) => RatingDisplayBaseState;

// @public (undocumented)
export const useRatingDisplayContextValues: (state: RatingDisplayState) => RatingDisplayContextValues;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ export type {
RatingContextValues,
RatingOnChangeEventData,
RatingProps,
RatingBaseProps,
RatingSlots,
RatingState,
RatingBaseState,
} from './components/Rating/index';
export {
Rating,
Expand All @@ -12,4 +14,5 @@ export {
useRatingContextValues,
useRatingStyles_unstable,
useRating_unstable,
useRatingBase_unstable,
} from './components/Rating/index';
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
export type {
RatingDisplayContextValues,
RatingDisplayProps,
RatingDisplayBaseProps,
RatingDisplaySlots,
RatingDisplayState,
RatingDisplayBaseState,
} from './components/RatingDisplay/index';
export {
RatingDisplay,
Expand All @@ -11,4 +13,5 @@ export {
useRatingDisplayContextValues,
useRatingDisplayStyles_unstable,
useRatingDisplay_unstable,
useRatingDisplayBase_unstable,
} from './components/RatingDisplay/index';
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
export type {
RatingItemContextValue,
RatingItemProps,
RatingItemBaseProps,
RatingItemSlots,
RatingItemState,
RatingItemBaseState,
} from './components/RatingItem/index';
export {
RatingItem,
ratingItemClassNames,
renderRatingItem_unstable,
useRatingItemStyles_unstable,
useRatingItem_unstable,
useRatingItemBase_unstable,
} from './components/RatingItem/index';
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ export type RatingOnChangeEventData = EventData<'change', React.FormEvent<HTMLDi
value: number;
};

/**
* Rating base props — excludes design props (color, size).
*/
export type RatingBaseProps = Omit<RatingProps, 'color' | 'size'>;

/**
* State used in rendering Rating
*/
Expand All @@ -81,6 +86,11 @@ export type RatingState = ComponentState<RatingSlots> &
hoveredValue?: number | undefined;
};

/**
* Rating base state — excludes design props (color, size).
*/
export type RatingBaseState = Omit<RatingState, 'color' | 'size'>;

export type RatingContextValues = {
ratingItem: RatingItemContextValue;
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ export type {
RatingContextValues,
RatingOnChangeEventData,
RatingProps,
RatingBaseProps,
RatingSlots,
RatingState,
RatingBaseState,
} from './Rating.types';
export { renderRating_unstable } from './renderRating';
export { useRating_unstable } from './useRating';
export { useRating_unstable, useRatingBase_unstable } from './useRating';
export { ratingClassNames, useRatingStyles_unstable } from './useRatingStyles.styles';
export { useRatingContextValues } from './useRatingContextValues';
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

import { assertSlots } from '@fluentui/react-utilities';
import type { JSXElement } from '@fluentui/react-utilities';
import type { RatingState, RatingSlots, RatingContextValues } from './Rating.types';
import type { RatingBaseState, RatingSlots, RatingContextValues } from './Rating.types';
import { RatingItemProvider } from '../../contexts/RatingItemContext';

/**
* Render the final JSX of Rating
*/
export const renderRating_unstable = (state: RatingState, contextValues: RatingContextValues): JSXElement => {
export const renderRating_unstable = (state: RatingBaseState, contextValues: RatingContextValues): JSXElement => {
assertSlots<RatingSlots>(state);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
useControllableState,
useId,
} from '@fluentui/react-utilities';
import type { RatingProps, RatingState } from './Rating.types';
import type { RatingBaseProps, RatingBaseState, RatingProps, RatingState } from './Rating.types';
import { RatingItem } from '../../RatingItem';
import { StarFilled, StarRegular } from '@fluentui/react-icons';

Expand All @@ -23,16 +23,46 @@ import { StarFilled, StarRegular } from '@fluentui/react-icons';
* @param ref - reference to root HTMLElement of Rating
*/
export const useRating_unstable = (props: RatingProps, ref: React.Ref<HTMLDivElement>): RatingState => {
const generatedName = useId('rating-');
const {
color = 'neutral',
size = 'extra-large',
iconFilled = StarFilled,
iconOutline = StarRegular,
...baseProps
} = props;
const state = useRatingBase_unstable(
{
iconFilled,
iconOutline,
...baseProps,
},
ref,
);

return {
...state,
color,
size,
};
};

/**
* Base hook for Rating component. Manages state related to controlled/uncontrolled
* rating value, hover state, radiogroup ARIA role, and keyboard/mouse interaction —
* without design props (color, size).
*
* @param props - props from this instance of Rating (without color, size)
* @param ref - reference to root HTMLElement of Rating
*/
export const useRatingBase_unstable = (props: RatingBaseProps, ref: React.Ref<HTMLDivElement>): RatingBaseState => {
const generatedName = useId('rating-');
const {
iconFilled = 'span',
iconOutline = 'span',
max = 5,
name = generatedName,
onChange,
step = 1,
size = 'extra-large',
itemLabel,
} = props;

Expand All @@ -52,13 +82,11 @@ export const useRating_unstable = (props: RatingProps, ref: React.Ref<HTMLDivEle
return Array.from(Array(max), (_, i) => <RatingItem value={i + 1} key={i + 1} />);
}, [max]);

const state: RatingState = {
color,
const state: RatingBaseState = {
iconFilled,
iconOutline,
name,
step,
size,
itemLabel,
value,
hoveredValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,22 @@ export type RatingDisplayProps = ComponentProps<RatingDisplaySlots> & {
value?: number;
};

/**
* RatingDisplay base props — excludes design props (color, size).
*/
export type RatingDisplayBaseProps = Omit<RatingDisplayProps, 'color' | 'size'>;

/**
* State used in rendering RatingDisplay
*/
export type RatingDisplayState = ComponentState<RatingDisplaySlots> &
Required<Pick<RatingDisplayProps, 'color' | 'compact' | 'icon' | 'max' | 'size'>> &
Pick<RatingDisplayProps, 'value'>;

/**
* RatingDisplay base state — excludes design props (color, size).
*/
export type RatingDisplayBaseState = Omit<RatingDisplayState, 'color' | 'size' | 'icon'> &
Pick<RatingDisplayProps, 'icon'>;

export type RatingDisplayContextValues = { ratingItem: RatingItemContextValue };
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ export { RatingDisplay } from './RatingDisplay';
export type {
RatingDisplayContextValues,
RatingDisplayProps,
RatingDisplayBaseProps,
RatingDisplaySlots,
RatingDisplayState,
RatingDisplayBaseState,
} from './RatingDisplay.types';
export { renderRatingDisplay_unstable } from './renderRatingDisplay';
export { useRatingDisplay_unstable } from './useRatingDisplay';
export { useRatingDisplay_unstable, useRatingDisplayBase_unstable } from './useRatingDisplay';
export { ratingDisplayClassNames, useRatingDisplayStyles_unstable } from './useRatingDisplayStyles.styles';
export { useRatingDisplayContextValues } from './useRatingDisplayContextValues';
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@

import { assertSlots } from '@fluentui/react-utilities';
import type { JSXElement } from '@fluentui/react-utilities';
import type { RatingDisplayState, RatingDisplaySlots, RatingDisplayContextValues } from './RatingDisplay.types';
import type { RatingDisplayBaseState, RatingDisplaySlots, RatingDisplayContextValues } from './RatingDisplay.types';
import { RatingItemProvider } from '../../contexts/RatingItemContext';

/**
* Render the final JSX of RatingDisplay
*/
export const renderRatingDisplay_unstable = (
state: RatingDisplayState,
state: RatingDisplayBaseState,
contextValues: RatingDisplayContextValues,
): JSXElement => {
assertSlots<RatingDisplaySlots>(state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

import * as React from 'react';
import { getIntrinsicElementProps, slot, useId } from '@fluentui/react-utilities';
import type { RatingDisplayProps, RatingDisplayState } from './RatingDisplay.types';
import type {
RatingDisplayBaseProps,
RatingDisplayBaseState,
RatingDisplayProps,
RatingDisplayState,
} from './RatingDisplay.types';
import { StarFilled } from '@fluentui/react-icons';
import { RatingItem } from '../RatingItem/RatingItem';

Expand All @@ -19,7 +24,30 @@ export const useRatingDisplay_unstable = (
props: RatingDisplayProps,
ref: React.Ref<HTMLDivElement>,
): RatingDisplayState => {
const { color = 'neutral', count, compact = false, icon = StarFilled, max = 5, size = 'medium', value } = props;
const { color = 'neutral', size = 'medium', icon = StarFilled, ...baseProps } = props;
const state = useRatingDisplayBase_unstable({ icon, ...baseProps }, ref);

return {
...state,
icon,
color,
size,
};
};

/**
* Base hook for RatingDisplay component. Manages state related to ARIA img role,
* aria-labelledby composition from valueText/countText IDs, slot structure, and
* compact/full display modes — without design props (color, size).
*
* @param props - props from this instance of RatingDisplay (without color, size)
* @param ref - reference to root HTMLDivElement of RatingDisplay
*/
export const useRatingDisplayBase_unstable = (
props: RatingDisplayBaseProps,
ref: React.Ref<HTMLDivElement>,
): RatingDisplayBaseState => {
const { count, compact = false, icon, max = 5, value } = props;

const valueTextId = useId('rating-value-');
const countTextId = useId('rating-count-');
Expand All @@ -33,12 +61,10 @@ export const useRatingDisplay_unstable = (
);
}, [compact, max]);

const state: RatingDisplayState = {
color,
const state: RatingDisplayBaseState = {
compact,
icon,
max,
size,
value,
components: {
root: 'div',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ export type RatingItemProps = ComponentProps<Partial<RatingItemSlots>> & {
value?: number;
};

/**
* RatingItem base props — same as RatingItemProps (no design-only props at this level).
*/
export type RatingItemBaseProps = RatingItemProps;

/**
* State used in rendering RatingItem
*/
Expand All @@ -46,6 +51,11 @@ export type RatingItemState = ComponentState<RatingItemSlots> &
appearance: 'outline' | 'filled';
};

/**
* RatingItem base state — excludes design props (color, size) from context.
*/
export type RatingItemBaseState = Omit<RatingItemState, 'color' | 'size'>;

export type RatingItemContextValue = Partial<Pick<RatingState, 'name' | 'hoveredValue' | 'value'>> &
Pick<RatingState, 'color' | 'iconFilled' | 'iconOutline' | 'itemLabel' | 'step' | 'size'> &
Partial<Pick<RatingDisplayState, 'compact'>> & {
Expand Down
Loading
Loading