UNPKG

@workday/canvas-kit-react

Version:

The parent module that contains all Workday Canvas Kit React components

77 lines (76 loc) 2.47 kB
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 }; });