136 lines
4.5 KiB
JavaScript
136 lines
4.5 KiB
JavaScript
'use client';
|
|
import * as React from 'react';
|
|
import { useEventCallback, useControllableState, getIntrinsicElementProps, slot } from '@fluentui/react-utilities';
|
|
import { useArrowNavigationGroup } from '@fluentui/react-tabster';
|
|
/**
|
|
* Create the state required to render Toolbar.
|
|
*
|
|
* The returned state can be modified with hooks such as useToolbarStyles_unstable,
|
|
* before being passed to renderToolbar_unstable.
|
|
*
|
|
* @param props - props from this instance of Toolbar
|
|
* @param ref - reference to root HTMLElement of Toolbar
|
|
*/ export const useToolbar_unstable = (props, ref)=>{
|
|
const { size = 'medium' } = props;
|
|
const state = useToolbarBase_unstable(props, ref);
|
|
const arrowNavigationProps = useToolbarArrowNavigationProps_unstable();
|
|
return {
|
|
size,
|
|
...state,
|
|
root: {
|
|
...state.root,
|
|
...arrowNavigationProps
|
|
}
|
|
};
|
|
};
|
|
/**
|
|
* Base hook that builds Toolbar state for behavior and structure only.
|
|
* It does not add arrow key navigation, which is handled by `useToolbar_unstable`.
|
|
*
|
|
* @internal
|
|
* @param props - Props for this Toolbar instance.
|
|
* @param ref - Ref to the root HTMLElement.
|
|
*/ export const useToolbarBase_unstable = (props, ref)=>{
|
|
const { vertical = false } = props;
|
|
const initialState = {
|
|
vertical,
|
|
// TODO add appropriate props/defaults
|
|
components: {
|
|
// TODO add each slot's element type or component
|
|
root: 'div'
|
|
},
|
|
// TODO add appropriate slots, for example:
|
|
// mySlot: resolveShorthand(props.mySlot),
|
|
root: slot.always(getIntrinsicElementProps('div', {
|
|
role: 'toolbar',
|
|
ref: ref,
|
|
...vertical && {
|
|
'aria-orientation': 'vertical'
|
|
},
|
|
...props
|
|
}), {
|
|
elementType: 'div'
|
|
})
|
|
};
|
|
const [checkedValues, onCheckedValueChange] = useToolbarSelectableState({
|
|
checkedValues: props.checkedValues,
|
|
defaultCheckedValues: props.defaultCheckedValues,
|
|
onCheckedValueChange: props.onCheckedValueChange
|
|
});
|
|
const handleToggleButton = useEventCallback((e, name, value, checked)=>{
|
|
if (name && value) {
|
|
const checkedItems = (checkedValues === null || checkedValues === void 0 ? void 0 : checkedValues[name]) || [];
|
|
const newCheckedItems = [
|
|
...checkedItems
|
|
];
|
|
if (checked) {
|
|
newCheckedItems.splice(newCheckedItems.indexOf(value), 1);
|
|
} else {
|
|
newCheckedItems.push(value);
|
|
}
|
|
onCheckedValueChange === null || onCheckedValueChange === void 0 ? void 0 : onCheckedValueChange(e, {
|
|
name,
|
|
checkedItems: newCheckedItems
|
|
});
|
|
}
|
|
});
|
|
const handleRadio = useEventCallback((e, name, value, checked)=>{
|
|
if (name && value) {
|
|
onCheckedValueChange === null || onCheckedValueChange === void 0 ? void 0 : onCheckedValueChange(e, {
|
|
name,
|
|
checkedItems: [
|
|
value
|
|
]
|
|
});
|
|
}
|
|
});
|
|
return {
|
|
...initialState,
|
|
handleToggleButton,
|
|
handleRadio,
|
|
checkedValues: checkedValues !== null && checkedValues !== void 0 ? checkedValues : {}
|
|
};
|
|
};
|
|
/**
|
|
* Adds appropriate state values and handlers for selectable items
|
|
* i.e checkboxes and radios
|
|
*/ const useToolbarSelectableState = (state)=>{
|
|
const [checkedValues, setCheckedValues] = useControllableState({
|
|
state: state.checkedValues,
|
|
defaultState: state.defaultCheckedValues,
|
|
initialState: {}
|
|
});
|
|
const { onCheckedValueChange: onCheckedValueChangeOriginal } = state;
|
|
const onCheckedValueChange = useEventCallback((e, { name, checkedItems })=>{
|
|
if (onCheckedValueChangeOriginal) {
|
|
onCheckedValueChangeOriginal(e, {
|
|
name,
|
|
checkedItems
|
|
});
|
|
}
|
|
setCheckedValues((s)=>{
|
|
return s ? {
|
|
...s,
|
|
[name]: checkedItems
|
|
} : {
|
|
[name]: checkedItems
|
|
};
|
|
});
|
|
});
|
|
return [
|
|
checkedValues,
|
|
onCheckedValueChange
|
|
];
|
|
};
|
|
/**
|
|
* Hook to add arrow navigation props to the Toolbar.
|
|
*
|
|
* @internal
|
|
* @returns - Tabster DOM attributes for arrow navigation
|
|
*/ export const useToolbarArrowNavigationProps_unstable = ()=>{
|
|
return useArrowNavigationGroup({
|
|
circular: true,
|
|
axis: 'both'
|
|
});
|
|
};
|