UNPKG

@workday/canvas-kit-react

Version:

The parent module that contains all Workday Canvas Kit React components

123 lines (122 loc) 4.79 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.useTabsModel = void 0; const react_1 = __importDefault(require("react")); const common_1 = require("@workday/canvas-kit-react/common"); const collection_1 = require("@workday/canvas-kit-react/collection"); const menu_1 = require("@workday/canvas-kit-react/menu"); /** * The TabsModel extends the [Collection * System](/getting-started/for-developers/resources/collection-api/). Tabs have tab items and * panels. Tabs can be overflowed if there isn't enough room to render and will overflow to a * {@link MenuModel} sub-model. * * ```tsx * const model = useTabsModel({ * onSelect(data) { * console.log('Selected Tab', data) * } * }) * * <Tabs model={model}>{Tabs child components}</Tabs> * ``` */ exports.useTabsModel = (0, common_1.createModelHook)({ defaultConfig: { ...collection_1.useOverflowListModel.defaultConfig, /** * Optional id for the whole `Tabs` group. The `aria-controls` of the `Tab.Item` and `id` of the * `Tab.Panel` will automatically derived from this id. If not provided, a unique id will be * created. * @default useUniqueId() */ id: '', /** * An initially selected tab. This value must match the `name` of the `Tab.Item` component. If * not provided, the first tab will be selected. */ initialTab: '', /** * The default Tabs sub-components only handle rendering of tabs in a horizontal orientation, but * the sub-components could be replaced to handle vertical orientations. * @default 'horizontal' */ orientation: 'horizontal', menuConfig: {}, }, requiredConfig: collection_1.useOverflowListModel.requiredConfig, contextOverride: collection_1.useOverflowListModel.Context, })(config => { var _a; const initialSelectedRef = react_1.default.useRef(config.initialTab); const getId = config.getId || collection_1.defaultGetId; const modality = (0, common_1.useModalityType)(); const model = (0, collection_1.useOverflowListModel)(collection_1.useOverflowListModel.mergeConfig(config, { shouldCalculateOverflow: modality !== 'touch', orientation: config.orientation || 'horizontal', onRegisterItem(data) { if (!initialSelectedRef.current) { initialSelectedRef.current = data.id; events.select({ id: initialSelectedRef.current }); } }, initialSelectedIds: config.initialTab ? [config.initialTab] : ((_a = config.items) === null || _a === void 0 ? void 0 : _a.length) ? [getId(config.items[0])] : [], shouldVirtualize: false, })); const panels = (0, collection_1.useListModel)(); const state = { ...model.state, getId, orientation: config.orientation || 'horizontal', /** * A list of panels. Uses `ListModel` */ panels: panels.state.items, /** * A React.Ref of the current item index. A ref is used to allow for updating outside the normal * React state cycle to ensure accurate index tracking as items are registered within the same * state setting phase. */ panelIndexRef: panels.state.indexRef, }; const overflowItems = react_1.default.useMemo(() => config.items ? config.items.filter(item => state.hiddenIds.includes(getId(item))) : undefined, // eslint-disable-next-line react-hooks/exhaustive-deps [state.hiddenIds, config.items]); const events = { ...model.events, /** * This event registers panels with state.panels. Called when a panel is mounted. */ registerPanel: panels.events.registerItem, /** * This event unregisters panels with state.panels. Called when a panel is unmounted. */ unregisterPanel: panels.events.unregisterItem, }; const menu = (0, menu_1.useMenuModel)(menu_1.useMenuModel.mergeConfig(config.menuConfig, { id: `menu-${model.state.id}`, items: overflowItems, nonInteractiveIds: state.nonInteractiveIds.filter(key => !state.hiddenIds.includes(key)), onSelect(data) { menu.events.hide(); events.select(data); }, onShow() { // Always select the first item when the menu is opened menu.events.goToFirst(); }, })); return { ...model, state, events, menu, }; });