@workday/canvas-kit-react
Version:
The parent module that contains all Workday Canvas Kit React components
185 lines (184 loc) • 8.45 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useOverflowListModel = exports.getHiddenIds = void 0;
const react_1 = __importDefault(require("react"));
const common_1 = require("@workday/canvas-kit-react/common");
const useSelectionListModel_1 = require("./useSelectionListModel");
function getHiddenIds(containerSize, containerGap, overflowTargetSize, itemSizeCache, selectedIds, items) {
/** Allows us to prioritize showing the selected item */
let selectedKey;
/** Tally of combined item widths. We'll add items that fit until the container is full */
let itemSize = 0;
/** Tally ids that won't fit inside the container. These will be used by components to hide
* elements that won't fit in the container */
const hiddenIds = [];
/** Track if gap should be calculated since gap doesn't apply to the width of the first item, only
* consecutive items */
let shouldAddGap = false;
if (selectedIds !== 'all' && selectedIds.length) {
if (items.length) {
// If selectedIds[0] is not in items, use the first id from items
selectedKey = items.find(item => item.id === selectedIds[0]) ? selectedIds[0] : items[0].id;
}
}
if (Object.keys(itemSizeCache).reduce((sum, key, index) => sum + itemSizeCache[key] + (index > 0 ? containerGap : 0), 0) <= containerSize) {
// All items fit, return empty array
return [];
}
else if (selectedKey) {
if (itemSizeCache[selectedKey] + overflowTargetSize > containerSize) {
// If the selected item doesn't fit, only show overflow (all items hidden)
return Object.keys(itemSizeCache);
}
else {
// at least the selected item and overflow target fit. Update our itemWidth with the sum
itemSize += itemSizeCache[selectedKey] + overflowTargetSize;
shouldAddGap = true;
}
}
else {
itemSize += overflowTargetSize;
}
for (const key in itemSizeCache) {
if (key !== selectedKey) {
itemSize += itemSizeCache[key] + (shouldAddGap ? containerGap : 0);
shouldAddGap = true;
if (itemSize > containerSize) {
hiddenIds.push(key);
}
}
}
return hiddenIds;
}
exports.getHiddenIds = getHiddenIds;
exports.useOverflowListModel = (0, common_1.createModelHook)({
defaultConfig: {
...useSelectionListModel_1.useSelectionListModel.defaultConfig,
initialHiddenIds: [],
containerWidth: 0,
/**
* Determines if overflow should actually occur. For example, touch devices are better at
* side-scrolling than mouse devices. In these cases, it makes sense to disable overflowing.
* @default true
*/ shouldCalculateOverflow: true,
},
requiredConfig: useSelectionListModel_1.useSelectionListModel.requiredConfig,
contextOverride: useSelectionListModel_1.useSelectionListModel.Context,
})(config => {
const shouldCalculateOverflow = config.shouldCalculateOverflow === undefined ? true : config.shouldCalculateOverflow;
const [hiddenIds, setHiddenIds] = react_1.default.useState(config.initialHiddenIds);
const [itemSizeCache, setItemSizeCache] = react_1.default.useState({});
const [containerSize, setContainerSize] = react_1.default.useState(0);
const [containerGap, setContainerGap] = react_1.default.useState(0);
const containerSizeRef = react_1.default.useRef(0);
const itemSizeCacheRef = react_1.default.useRef(itemSizeCache);
const [overflowTargetWidth, setOverflowTargetWidth] = react_1.default.useState(0);
const overflowTargetSizeRef = react_1.default.useRef(0);
const internalHiddenIds = shouldCalculateOverflow ? hiddenIds : [];
// Cursors skip over disabled ids, but know nothing of hidden ids. We'll go ahead and disable
// hidden ids as well
const nonInteractiveIds = (config.nonInteractiveIds || []).concat(internalHiddenIds);
const model = (0, useSelectionListModel_1.useSelectionListModel)({
...config,
nonInteractiveIds,
});
const state = {
...model.state,
hiddenIds: internalHiddenIds,
itemSizeCache,
/**
* @deprecated Use `itemSizeCache` instead
*/
itemWidthCache: itemSizeCache,
containerSize,
/**
* @deprecated Use `containerSize` instead
*/
containerWidth: containerSize,
containerGap,
overflowTargetWidth,
};
const events = {
...model.events,
select(data) {
const { selectedIds } = model.selection.select(data.id, state);
const ids = getHiddenIds(containerSizeRef.current, containerGap, overflowTargetSizeRef.current, itemSizeCacheRef.current, selectedIds, config.items);
model.events.select(data);
setHiddenIds(ids);
},
setContainerSize(data) {
containerSizeRef.current =
model.state.orientation === 'horizontal' ? data.width || 0 : data.height || 0;
setContainerSize(containerSizeRef.current);
const ids = getHiddenIds(containerSizeRef.current, containerGap, overflowTargetSizeRef.current, itemSizeCacheRef.current, state.selectedIds, config.items);
setHiddenIds(ids);
},
/**
* @deprecated Use `setContainerSize` instead and pass both `width` and `height`
*/
setContainerWidth(data) {
events.setContainerSize({ width: data.width, height: 0 });
},
setContainerGap(data) {
setContainerGap(data.size);
const ids = getHiddenIds(containerSizeRef.current, data.size, overflowTargetSizeRef.current, itemSizeCacheRef.current, state.selectedIds, config.items);
setHiddenIds(ids);
},
setOverflowTargetSize(data) {
overflowTargetSizeRef.current =
model.state.orientation === 'horizontal' ? data.width || 0 : data.height || 0;
setOverflowTargetWidth(overflowTargetSizeRef.current);
},
/**
*
* @deprecated `setOverflowTargetWidth` is deprecated. Please use `setOverflowTargetSize` and pass in the `width` and set `height` to `0`.
*/
setOverflowTargetWidth(data) {
overflowTargetSizeRef.current = data.width;
events.setOverflowTargetSize({ width: overflowTargetSizeRef.current, height: 0 });
},
/**
*
* @deprecated `addItemWidth` is deprecated. Please use `addItemSize` and set the `width`
*/
addItemWidth(data) {
events.addItemSize({ id: data.id, width: data.width, height: 0 });
},
addItemSize(data) {
itemSizeCacheRef.current = {
...itemSizeCacheRef.current,
[data.id]: model.state.orientation === 'horizontal' ? data.width : data.height,
};
setItemSizeCache(itemSizeCacheRef.current);
const ids = getHiddenIds(containerSizeRef.current, containerGap, overflowTargetSizeRef.current, itemSizeCacheRef.current, state.selectedIds, config.items);
setHiddenIds(ids);
},
removeItemSize(data) {
const newCache = { ...itemSizeCacheRef.current };
delete newCache[data.id];
itemSizeCacheRef.current = newCache;
setItemSizeCache(itemSizeCacheRef.current);
const ids = getHiddenIds(containerSizeRef.current, containerGap, overflowTargetSizeRef.current, itemSizeCacheRef.current, state.selectedIds !== 'all'
? state.selectedIds.filter(sId => data.id !== sId)
: state.selectedIds, config.items);
setHiddenIds(ids);
},
/**
*
* @deprecated `removeItemWidth` is deprecated. Please use `removeItemSize`.
*/
removeItemWidth(data) {
events.removeItemSize({ id: data.id });
},
addHiddenKey(data) {
setHiddenIds(ids => ids.concat(data.id));
},
removeHiddenKey(data) {
setHiddenIds(ids => ids.filter(key => key !== data.id));
},
};
return { ...model, state, events };
});
;