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 @@
{
Comment thread
mainframev marked this conversation as resolved.
"type": "minor",
"comment": "feat: export useTagPickerContextValues and TagPickerControlInternalSlots for headless composition",
"packageName": "@fluentui/react-tag-picker",
"email": "vgenaev@gmail.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ export const renderTagPickerOptionGroup: (state: TagPickerOptionGroupState) => J
export const TagPicker: React_2.FC<TagPickerProps>;

// @public
export type TagPickerBaseProps = DistributiveOmit<TagPickerProps, 'positioning'>;
export type TagPickerBaseProps = DistributiveOmit<TagPickerProps, 'positioning' | 'size' | 'appearance' | 'inline'>;

// @public
export type TagPickerBaseState = Omit<TagPickerState, 'size' | 'appearance' | 'inline'>;

// @public
export const TagPickerButton: ForwardRefComponent<TagPickerButtonProps>;
Expand Down Expand Up @@ -129,6 +132,11 @@ export type TagPickerControlBaseState = DistributiveOmit<TagPickerControlState,
// @public (undocumented)
export const tagPickerControlClassNames: SlotClassNames<TagPickerControlSlots & TagPickerControlInternalSlots>;

// @public (undocumented)
export type TagPickerControlInternalSlots = {
aside?: NonNullable<Slot<'span'>>;
};

// @public
export type TagPickerControlProps = ComponentProps<Partial<TagPickerControlSlots>>;

Expand Down Expand Up @@ -285,7 +293,7 @@ export type TagPickerState = ComponentState<TagPickerSlots> & Pick<ComboboxState
export const useTagPicker_unstable: (props: TagPickerProps) => TagPickerState;

// @public
export const useTagPickerBase_unstable: (props: TagPickerBaseProps) => TagPickerState;
export const useTagPickerBase_unstable: (props: TagPickerBaseProps) => TagPickerBaseState;

// @public
export const useTagPickerButton_unstable: (props: TagPickerButtonProps, ref: React_2.Ref<HTMLButtonElement>) => TagPickerButtonState;
Expand All @@ -299,6 +307,9 @@ export const useTagPickerButtonStyles_unstable: (state: TagPickerButtonState) =>
// @public (undocumented)
export const useTagPickerContext_unstable: <T>(selector: ContextSelector<TagPickerContextValue, T>) => T;

// @public (undocumented)
export function useTagPickerContextValues(state: TagPickerState): TagPickerContextValues;

// @public
export const useTagPickerControl_unstable: (props: TagPickerControlProps, ref: React_2.Ref<HTMLDivElement>) => TagPickerControlState;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export type {
TagPickerBaseProps,
TagPickerBaseState,
TagPickerContextValues,
TagPickerOnOpenChangeData,
TagPickerOnOptionSelectData,
Expand All @@ -13,4 +14,5 @@ export {
renderTagPicker_unstable,
useTagPicker_unstable,
useTagPickerBase_unstable,
useTagPickerContextValues,
} from './components/TagPicker/index';
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,16 @@ export type TagPickerContextValues = {
};

/**
* TagPicker Base Props - omits the floating-ui `positioning` prop; the styled wrapper
* {@link TagPickerProps} re-introduces it via `usePositioning`.
* TagPicker Base Props - omits the presentation-related props that the base hook does not handle:
* the floating-ui `positioning` prop (the styled {@link TagPickerProps} re-introduces it via
* `usePositioning`) as well as `size`, `appearance` and `inline` (layered on by the styled
* {@link useTagPicker_unstable} hook).
*/
export type TagPickerBaseProps = DistributiveOmit<TagPickerProps, 'positioning'>;
export type TagPickerBaseProps = DistributiveOmit<TagPickerProps, 'positioning' | 'size' | 'appearance' | 'inline'>;

/**
* TagPicker Base State - the state produced by the base hook, which does not interact with the
* `size`, `appearance` and `inline` props. These are layered on by the styled
* {@link useTagPicker_unstable} hook.
*/
export type TagPickerBaseState = Omit<TagPickerState, 'size' | 'appearance' | 'inline'>;
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { TagPicker } from './TagPicker';
export type {
TagPickerBaseProps,
TagPickerBaseState,
TagPickerContextValues,
TagPickerOnOpenChangeData,
TagPickerOnOptionSelectData,
Expand All @@ -11,3 +12,4 @@ export type {
} from './TagPicker.types';
export { renderTagPicker_unstable } from './renderTagPicker';
export { useTagPicker_unstable, useTagPickerBase_unstable } from './useTagPicker';
export { useTagPickerContextValues } from './useTagPickerContextValues';
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,22 @@ describe('useTagPicker_unstable', () => {
expect(result.current.noPopover).toBe(false);
});

it('defaults appearance to "outline"', () => {
const { result } = renderRoot();
expect(result.current.appearance).toBe('outline');
});

it('honors explicit size and inline props', () => {
const { result } = renderRoot({ size: 'large', inline: true });
expect(result.current.size).toBe('large');
expect(result.current.inline).toBe(true);
});

it('honors an explicit appearance prop', () => {
const { result } = renderRoot({ appearance: 'filled-darker' });
expect(result.current.appearance).toBe('filled-darker');
});

it('generates a non-empty popoverId', () => {
const { result } = renderRoot();
expect(result.current.popoverId.length).toBeGreaterThan(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as React from 'react';
import { elementContains, useEventCallback, useId, useMergedRefs } from '@fluentui/react-utilities';
import type {
TagPickerBaseProps,
TagPickerBaseState,
TagPickerOnOpenChangeData,
TagPickerOnOptionSelectData,
TagPickerProps,
Expand All @@ -22,13 +23,13 @@ const fallbackPositions: PositioningShorthandValue[] = ['above', 'after', 'after
* Create the base state required to render TagPicker, without floating-ui positioning.
* @param props - props from this instance of TagPicker (without `positioning`)
*/
export const useTagPickerBase_unstable = (props: TagPickerBaseProps): TagPickerState => {
export const useTagPickerBase_unstable = (props: TagPickerBaseProps): TagPickerBaseState => {
const popoverId = useId('picker-listbox');
const triggerInnerRef = React.useRef<HTMLInputElement | HTMLButtonElement>(null);
const secondaryActionRef = React.useRef<HTMLSpanElement>(null);
const tagPickerGroupRef = React.useRef<HTMLDivElement>(null);
const passiveTargetRef = React.useRef<HTMLDivElement>(null);
const { size = 'medium', inline = false, noPopover = false, disableAutoFocus } = props;
const { noPopover = false, disableAutoFocus } = props;

const {
controller: activeDescendantController,
Expand Down Expand Up @@ -59,7 +60,6 @@ export const useTagPickerBase_unstable = (props: TagPickerBaseProps): TagPickerS
disableAutoFocus,
editable: true,
multiselect: true,
size: 'medium',
});

const { trigger, popover } = childrenToTriggerAndPopover(props.children, noPopover);
Expand All @@ -76,15 +76,12 @@ export const useTagPickerBase_unstable = (props: TagPickerBaseProps): TagPickerS
secondaryActionRef,
tagPickerGroupRef,
targetRef: passiveTargetRef,
size,
inline,
open: comboboxState.open,
mountNode: comboboxState.mountNode,
onOptionClick: useEventCallback(event => {
comboboxState.onOptionClick(event);
comboboxState.setOpen(event, false);
}),
appearance: comboboxState.appearance,
clearSelection: comboboxState.clearSelection,
getOptionById: comboboxState.getOptionById,
getOptionsMatchingValue: comboboxState.getOptionsMatchingValue,
Expand Down Expand Up @@ -123,7 +120,7 @@ export const useTagPickerBase_unstable = (props: TagPickerBaseProps): TagPickerS
* @param props - props from this instance of Picker
*/
export const useTagPicker_unstable = (props: TagPickerProps): TagPickerState => {
const { positioning } = props;
const { positioning, size = 'medium', appearance = 'outline', inline = false } = props;

Comment thread
mainframev marked this conversation as resolved.
const { targetRef, containerRef } = usePositioning({
position: 'below' as const,
Expand All @@ -138,6 +135,9 @@ export const useTagPicker_unstable = (props: TagPickerProps): TagPickerState =>

return {
...baseState,
size,
appearance,
inline,
targetRef,
popoverRef: useMergedRefs(baseState.popoverRef, containerRef),
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
export { TagPicker, renderTagPicker_unstable, useTagPicker_unstable, useTagPickerBase_unstable } from './TagPicker';
export {
TagPicker,
renderTagPicker_unstable,
useTagPicker_unstable,
useTagPickerBase_unstable,
useTagPickerContextValues,
} from './TagPicker';
export type {
TagPickerBaseProps,
TagPickerBaseState,
TagPickerContextValues,
TagPickerProps,
TagPickerSlots,
Expand Down Expand Up @@ -57,6 +64,7 @@ export {
} from './TagPickerControl';
export type {
TagPickerControlBaseState,
TagPickerControlInternalSlots,
TagPickerControlProps,
TagPickerControlSlots,
TagPickerControlState,
Expand Down
Loading