@workday/canvas-kit-react
Version:
The parent module that contains all Workday Canvas Kit React components
123 lines (122 loc) • 4.79 kB
JavaScript
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,
};
});
;