@workday/canvas-kit-react
Version:
The parent module that contains all Workday Canvas Kit React components
77 lines (76 loc) • 2.47 kB
JavaScript
import React from 'react';
import { createModelHook } from '@workday/canvas-kit-react/common';
import { useMenuModel } from '@workday/canvas-kit-react/menu';
/**
* An input model can be used by compound components that need to work with form fields. Some form
* libraries use `onChange` and `value` to update a form object. Others use `onChange` and `ref` to
* avoid rerendering. Also autocomplete and test libraries may use the `value` `HTMLInputElement`
* property. We need to normalize these use cases so subcomponents can have correct data and all
* use-cases are supported.
*/
export const useInputModel = createModelHook({
defaultConfig: {
value: undefined,
onFilterChange(event) {
return;
},
onChange(event) {
return;
},
},
})(config => {
const inputRef = React.createRef();
return {
onFilterChange: config.onFilterChange,
onChange: config.onChange,
state: { value: config.value, inputRef },
events: {},
};
});
/**
* `ComboboxModel` extends the {@link ListModel} and the {@link InputModel}. Selecting items from
* the menu will dispatch an
* [input](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event) event on the
* input which should work with form libraries, automation, and autofill.
*
* ```tsx
* const model = useComboboxModel()
*
* <Combobox model={model}>{Combobox child components}</Combobox>
* ```
*/
export const useComboboxModel = createModelHook({
defaultConfig: {
...useInputModel.defaultConfig,
...useMenuModel.defaultConfig,
shouldVirtualize: true,
},
requiredConfig: {
...useInputModel.requiredConfig,
...useMenuModel.requiredConfig,
},
})(config => {
const input = useInputModel(config);
const menu = useMenuModel(config);
const [width, setWidth] = React.useState(0);
const state = {
/**
* The width of the combobox input. This is used to make sure the UI renders the menu the same
* width as the input.
*/
width,
...input.state,
...menu.state,
};
const events = {
...input.events,
...menu.events,
/**
* Change the width of the menu. Usually this is set to the width of the input.
*/
setWidth(width) {
setWidth(width);
},
};
return { ...menu, ...input, state, events };
});