first commit

This commit is contained in:
Stefan Hacker
2026-04-03 09:38:48 +02:00
commit 37ad745546
47450 changed files with 3120798 additions and 0 deletions
@@ -0,0 +1,3 @@
import type { IOverflowSetProps } from './OverflowSet.types';
import type { JSXElement } from '@fluentui/utilities';
export declare const OverflowButton: (props: IOverflowSetProps) => JSXElement;
@@ -0,0 +1,101 @@
import { __assign } from "tslib";
import * as React from 'react';
import { KeytipManager } from '../../utilities/keytips/KeytipManager';
import { useConst, usePrevious } from '@fluentui/react-hooks';
var registerPersistedKeytips = function (keytipsToRegister, keytipManager, registeredPersistedKeytips) {
for (var _i = 0, keytipsToRegister_1 = keytipsToRegister; _i < keytipsToRegister_1.length; _i++) {
var keytip = keytipsToRegister_1[_i];
var uniqueID = keytipManager.register(keytip, true);
// Update map
registeredPersistedKeytips[uniqueID] = keytip;
}
};
var unregisterPersistedKeytips = function (keytipManager, registeredPersistedKeytips) {
for (var _i = 0, _a = Object.keys(registeredPersistedKeytips); _i < _a.length; _i++) {
var uniqueID = _a[_i];
keytipManager.unregister(registeredPersistedKeytips[uniqueID], uniqueID, true);
delete registeredPersistedKeytips[uniqueID];
}
};
var useKeytipRegistrations = function (registeredPersistedKeytips, keytipsToRegister, keytipManager) {
var prevPersistedKeytips = usePrevious(registeredPersistedKeytips);
// Update
React.useEffect(function () {
if (prevPersistedKeytips) {
// Unregister old keytips
unregisterPersistedKeytips(keytipManager, prevPersistedKeytips);
// Register new keytips
registerPersistedKeytips(keytipsToRegister, keytipManager, registeredPersistedKeytips);
}
});
// Mount/Unmount
React.useEffect(function () {
// Register on mount
registerPersistedKeytips(keytipsToRegister, keytipManager, registeredPersistedKeytips);
return function () {
// Unregister on unmount
unregisterPersistedKeytips(keytipManager, registeredPersistedKeytips);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
};
export var OverflowButton = function (props) {
var keytipManager = KeytipManager.getInstance();
var className = props.className, overflowItems = props.overflowItems, keytipSequences = props.keytipSequences, itemSubMenuProvider = props.itemSubMenuProvider, onRenderOverflowButton = props.onRenderOverflowButton;
var persistedKeytips = useConst({});
// Gets the subMenu for an overflow item
var getSubMenuForItem = React.useCallback(function (item) {
// Checks if itemSubMenuProvider has been defined, if not defaults to subMenuProps
if (itemSubMenuProvider) {
return itemSubMenuProvider(item);
}
if (item.subMenuProps) {
return item.subMenuProps.items;
}
return undefined;
}, [itemSubMenuProvider]);
var _a = React.useMemo(function () {
var newKeytipsToRegister = [];
var newOverflowItems = [];
if (keytipSequences) {
overflowItems === null || overflowItems === void 0 ? void 0 : overflowItems.forEach(function (overflowItem) {
var _a;
var keytip = overflowItem.keytipProps;
if (keytip) {
// Create persisted keytip
var persistedKeytip = {
content: keytip.content,
keySequences: keytip.keySequences,
disabled: keytip.disabled || !!(overflowItem.disabled || overflowItem.isDisabled),
hasDynamicChildren: keytip.hasDynamicChildren,
hasMenu: keytip.hasMenu,
};
if (keytip.hasDynamicChildren || getSubMenuForItem(overflowItem)) {
// If the keytip has a submenu or children nodes, change onExecute to persistedKeytipExecute
persistedKeytip.onExecute = keytipManager.menuExecute.bind(keytipManager, keytipSequences, (_a = overflowItem === null || overflowItem === void 0 ? void 0 : overflowItem.keytipProps) === null || _a === void 0 ? void 0 : _a.keySequences);
persistedKeytip.hasOverflowSubMenu = true;
}
else {
// If the keytip doesn't have a submenu, just execute the original function
persistedKeytip.onExecute = keytip.onExecute;
}
newKeytipsToRegister.push(persistedKeytip);
// Add the overflow sequence to this item
var newOverflowItem = __assign(__assign({}, overflowItem), { keytipProps: __assign(__assign({}, keytip), { overflowSetSequence: keytipSequences }) });
newOverflowItems === null || newOverflowItems === void 0 ? void 0 : newOverflowItems.push(newOverflowItem);
}
else {
// Nothing to change, add overflowItem to list
newOverflowItems === null || newOverflowItems === void 0 ? void 0 : newOverflowItems.push(overflowItem);
}
});
}
else {
newOverflowItems = overflowItems;
}
return { modifiedOverflowItems: newOverflowItems, keytipsToRegister: newKeytipsToRegister };
}, [overflowItems, getSubMenuForItem, keytipManager, keytipSequences]), modifiedOverflowItems = _a.modifiedOverflowItems, keytipsToRegister = _a.keytipsToRegister;
useKeytipRegistrations(persistedKeytips, keytipsToRegister, keytipManager);
return React.createElement("div", { className: className }, onRenderOverflowButton(modifiedOverflowItems));
};
//# sourceMappingURL=OverflowButton.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
import * as React from 'react';
import type { IOverflowSetProps } from './OverflowSet.types';
export declare const OverflowSetBase: React.FunctionComponent<IOverflowSetProps>;
@@ -0,0 +1,46 @@
import { __assign } from "tslib";
import * as React from 'react';
import { useMergedRefs } from '@fluentui/react-hooks';
import { classNamesFunction, divProperties, elementContains, getNativeProps, focusFirstChild } from '../../Utilities';
import { OverflowButton } from './OverflowButton';
import { useDocumentEx } from '../../utilities/dom';
var getClassNames = classNamesFunction();
var COMPONENT_NAME = 'OverflowSet';
var useComponentRef = function (props, divContainer) {
var doc = useDocumentEx();
React.useImperativeHandle(props.componentRef, function () { return ({
focus: function (_forceIntoFirstElement, bypassHiddenElements) {
var focusSucceeded = false;
if (divContainer.current) {
focusSucceeded = focusFirstChild(divContainer.current, bypassHiddenElements);
}
return focusSucceeded;
},
focusElement: function (childElement) {
var focusSucceeded = false;
if (!childElement) {
return false;
}
if (divContainer.current && elementContains(divContainer.current, childElement)) {
childElement.focus();
focusSucceeded = (doc === null || doc === void 0 ? void 0 : doc.activeElement) === childElement;
}
return focusSucceeded;
},
}); }, [divContainer, doc]);
};
export var OverflowSetBase = React.forwardRef(function (props, forwardedRef) {
var divContainer = React.useRef(null);
var mergedRef = useMergedRefs(divContainer, forwardedRef);
useComponentRef(props, divContainer);
var items = props.items, overflowItems = props.overflowItems, className = props.className, styles = props.styles, vertical = props.vertical, role = props.role, _a = props.overflowSide, overflowSide = _a === void 0 ? 'end' : _a, onRenderItem = props.onRenderItem;
var classNames = getClassNames(styles, { className: className, vertical: vertical });
var showOverflow = !!overflowItems && overflowItems.length > 0;
return (React.createElement("div", __assign({}, getNativeProps(props, divProperties), { role: role || 'group', "aria-orientation": role === 'menubar' ? (vertical === true ? 'vertical' : 'horizontal') : undefined, className: classNames.root, ref: mergedRef }),
overflowSide === 'start' && showOverflow && React.createElement(OverflowButton, __assign({}, props, { className: classNames.overflowButton })),
items &&
items.map(function (item, i) { return (React.createElement("div", { className: classNames.item, key: item.key, role: "none" }, onRenderItem(item))); }),
overflowSide === 'end' && showOverflow && React.createElement(OverflowButton, __assign({}, props, { className: classNames.overflowButton }))));
});
OverflowSetBase.displayName = COMPONENT_NAME;
//# sourceMappingURL=OverflowSet.base.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
import * as React from 'react';
import type { IOverflowSetProps } from './OverflowSet.types';
export declare const OverflowSet: React.FunctionComponent<IOverflowSetProps>;
@@ -0,0 +1,7 @@
import { styled } from '../../Utilities';
import { OverflowSetBase } from './OverflowSet.base';
import { getStyles } from './OverflowSet.styles';
export var OverflowSet = styled(OverflowSetBase, getStyles, undefined, {
scope: 'OverflowSet',
});
//# sourceMappingURL=OverflowSet.js.map
@@ -0,0 +1 @@
{"version":3,"file":"OverflowSet.js","sourceRoot":"../src/","sources":["components/OverflowSet/OverflowSet.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD,MAAM,CAAC,IAAM,WAAW,GAA+C,MAAM,CAAC,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE;IACnH,KAAK,EAAE,aAAa;CACrB,CAAC,CAAC","sourcesContent":["import * as React from 'react';\nimport { styled } from '../../Utilities';\nimport { OverflowSetBase } from './OverflowSet.base';\nimport { getStyles } from './OverflowSet.styles';\nimport type { IOverflowSetProps } from './OverflowSet.types';\n\nexport const OverflowSet: React.FunctionComponent<IOverflowSetProps> = styled(OverflowSetBase, getStyles, undefined, {\n scope: 'OverflowSet',\n});\n"]}
@@ -0,0 +1,3 @@
import type { IOverflowSetStyles, IOverflowSetStyleProps } from './OverflowSet.types';
import type { IStyleFunction } from '../../Utilities';
export declare const getStyles: IStyleFunction<IOverflowSetStyleProps, IOverflowSetStyles>;
@@ -0,0 +1,22 @@
var overflowItemStyle = {
flexShrink: 0,
display: 'inherit',
};
export var getStyles = function (props) {
var className = props.className, vertical = props.vertical;
return {
root: [
'ms-OverflowSet',
{
position: 'relative',
display: 'flex',
flexWrap: 'nowrap',
},
vertical && { flexDirection: 'column' },
className,
],
item: ['ms-OverflowSet-item', overflowItemStyle],
overflowButton: ['ms-OverflowSet-overflowButton', overflowItemStyle],
};
};
//# sourceMappingURL=OverflowSet.styles.js.map
@@ -0,0 +1 @@
{"version":3,"file":"OverflowSet.styles.js","sourceRoot":"../src/","sources":["components/OverflowSet/OverflowSet.styles.ts"],"names":[],"mappings":"AAIA,IAAM,iBAAiB,GAAW;IAChC,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,SAAS;CACnB,CAAC;AAEF,MAAM,CAAC,IAAM,SAAS,GAA+D,UAAA,KAAK;IAChF,IAAA,SAAS,GAAe,KAAK,UAApB,EAAE,QAAQ,GAAK,KAAK,SAAV,CAAW;IACtC,OAAO;QACL,IAAI,EAAE;YACJ,gBAAgB;YAChB;gBACE,QAAQ,EAAE,UAAU;gBACpB,OAAO,EAAE,MAAM;gBACf,QAAQ,EAAE,QAAQ;aACnB;YACD,QAAQ,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE;YACvC,SAAS;SACV;QACD,IAAI,EAAE,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;QAChD,cAAc,EAAE,CAAC,+BAA+B,EAAE,iBAAiB,CAAC;KACrE,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import type { IOverflowSetStyles, IOverflowSetStyleProps } from './OverflowSet.types';\nimport type { IStyleFunction } from '../../Utilities';\nimport type { IStyle } from '../../Styling';\n\nconst overflowItemStyle: IStyle = {\n flexShrink: 0,\n display: 'inherit',\n};\n\nexport const getStyles: IStyleFunction<IOverflowSetStyleProps, IOverflowSetStyles> = props => {\n const { className, vertical } = props;\n return {\n root: [\n 'ms-OverflowSet',\n {\n position: 'relative',\n display: 'flex',\n flexWrap: 'nowrap',\n },\n vertical && { flexDirection: 'column' },\n className,\n ],\n item: ['ms-OverflowSet-item', overflowItemStyle],\n overflowButton: ['ms-OverflowSet-overflowButton', overflowItemStyle],\n };\n};\n"]}
@@ -0,0 +1,121 @@
import * as React from 'react';
import type { IKeytipProps } from '../../Keytip';
import type { IStyle } from '../../Styling';
import type { IRefObject, IRenderFunction, IStyleFunctionOrObject } from '../../Utilities';
/**
* {@docCategory OverflowSet}
*/
export interface IOverflowSet {
/**
* Sets focus to the first tabbable item in the zone.
* @param forceIntoFirstElement - If true, focus will be forced into the first element, even if
* @param bypassHiddenElements - If true, focus will be not be set on hidden elements.
* focus is already in the focus zone.
* @returns True if focus could be set to an active element, false if no operation was taken.
*/
focus(forceIntoFirstElement?: boolean, bypassHiddenElements?: boolean): boolean;
/**
* Sets focus to a specific child element within the zone. This can be used in conjunction with
* shouldReceiveFocus to created delayed focus scenarios (like animate the scroll position to the correct
* location and then focus.)
* @param childElement - The child element within the zone to focus.
* @returns True if focus could be set to an active element, false if no operation was taken.
*/
focusElement(childElement?: HTMLElement): boolean;
}
/**
* {@docCategory OverflowSet}
*/
export interface IOverflowSetProps extends React.RefAttributes<HTMLElement> {
/**
* Gets the component ref.
*/
componentRef?: IRefObject<IOverflowSet>;
/**
* Class name
*/
className?: string;
/**
* An array of items to be rendered by your onRenderItem function in the primary content area
*/
items?: IOverflowSetItemProps[];
/**
* Change item layout direction to vertical/stacked.
* If role is set to `menubar`, `vertical={true}` will also add proper `aria-orientation`.
* @defaultvalue false
*/
vertical?: boolean;
/**
* Controls wether or not the overflow button is placed at the start or end of the items.
* This gives a reversed visual behavior but maintains correct keyboard navigation.
* @defaultValue 'end'
*/
overflowSide?: 'start' | 'end';
/**
* An array of items to be passed to overflow contextual menu
*/
overflowItems?: IOverflowSetItemProps[];
/**
* Method to call when trying to render an item.
*/
onRenderItem: (item: IOverflowSetItemProps) => any;
/**
* Rendering method for overflow button and contextual menu. The argument to the function is
* the overflowItems passed in as props to this function.
*/
onRenderOverflowButton: IRenderFunction<any[]>;
/**
* The role for the OverflowSet.
* @defaultvalue 'group'
*/
role?: string;
/**
* Optional full keytip sequence for the overflow button, if it will have a keytip.
*/
keytipSequences?: string[];
/**
* Function that will take in an IOverflowSetItemProps and return the subMenu for that item.
* If not provided, will use 'item.subMenuProps.items' by default.
* Alternatively accepts a boolean, return True if the item has a menu and False if not
* This is only used if your overflow set has keytips.
*/
itemSubMenuProvider?: (item: IOverflowSetItemProps) => any[] | boolean | undefined;
/**
* Call to provide customized styling that will layer on top of the variant rules.
*/
styles?: IStyleFunctionOrObject<IOverflowSetProps, IOverflowSetStyles>;
}
/**
* {@docCategory OverflowSet}
*/
export interface IOverflowSetStyles {
/** The style that is layered onto the root element of OverflowSet. */
root?: IStyle;
/** The style that is layered onto each individual item in the overflow set. */
item?: IStyle;
/** The style that is layered onto the overflow button for the overflow set. */
overflowButton?: IStyle;
}
/**
* The props needed to construct styles.
* This represents the simplified set of immutable things which control the class names.
* {@docCategory OverflowSet}
*/
export type IOverflowSetStyleProps = Pick<IOverflowSetProps, 'vertical' | 'className'>;
/**
* {@docCategory OverflowSet}
*/
export interface IOverflowSetItemProps {
/**
* Unique id to identify the item.
*/
key: string;
/**
* Optional keytip for the overflowSetItem.
*/
keytipProps?: IKeytipProps;
/**
* Any additional properties to use when custom rendering menu items.
*/
[propertyName: string]: any;
}
@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=OverflowSet.types.js.map
@@ -0,0 +1 @@
{"version":3,"file":"OverflowSet.types.js","sourceRoot":"../src/","sources":["components/OverflowSet/OverflowSet.types.ts"],"names":[],"mappings":"","sourcesContent":["import * as React from 'react';\nimport type { IKeytipProps } from '../../Keytip';\nimport type { IStyle } from '../../Styling';\nimport type { IRefObject, IRenderFunction, IStyleFunctionOrObject } from '../../Utilities';\n\n/**\n * {@docCategory OverflowSet}\n */\nexport interface IOverflowSet {\n /**\n * Sets focus to the first tabbable item in the zone.\n * @param forceIntoFirstElement - If true, focus will be forced into the first element, even if\n * @param bypassHiddenElements - If true, focus will be not be set on hidden elements.\n * focus is already in the focus zone.\n * @returns True if focus could be set to an active element, false if no operation was taken.\n */\n focus(forceIntoFirstElement?: boolean, bypassHiddenElements?: boolean): boolean;\n\n /**\n * Sets focus to a specific child element within the zone. This can be used in conjunction with\n * shouldReceiveFocus to created delayed focus scenarios (like animate the scroll position to the correct\n * location and then focus.)\n * @param childElement - The child element within the zone to focus.\n * @returns True if focus could be set to an active element, false if no operation was taken.\n */\n focusElement(childElement?: HTMLElement): boolean;\n}\n\n/**\n * {@docCategory OverflowSet}\n */\nexport interface IOverflowSetProps extends React.RefAttributes<HTMLElement> {\n /**\n * Gets the component ref.\n */\n componentRef?: IRefObject<IOverflowSet>;\n\n /**\n * Class name\n */\n className?: string;\n\n /**\n * An array of items to be rendered by your onRenderItem function in the primary content area\n */\n items?: IOverflowSetItemProps[];\n\n /**\n * Change item layout direction to vertical/stacked.\n * If role is set to `menubar`, `vertical={true}` will also add proper `aria-orientation`.\n * @defaultvalue false\n */\n vertical?: boolean;\n\n /**\n * Controls wether or not the overflow button is placed at the start or end of the items.\n * This gives a reversed visual behavior but maintains correct keyboard navigation.\n * @defaultValue 'end'\n */\n overflowSide?: 'start' | 'end';\n\n /**\n * An array of items to be passed to overflow contextual menu\n */\n overflowItems?: IOverflowSetItemProps[];\n\n /**\n * Method to call when trying to render an item.\n */\n onRenderItem: (item: IOverflowSetItemProps) => any;\n\n /**\n * Rendering method for overflow button and contextual menu. The argument to the function is\n * the overflowItems passed in as props to this function.\n */\n onRenderOverflowButton: IRenderFunction<any[]>;\n\n /**\n * The role for the OverflowSet.\n * @defaultvalue 'group'\n */\n role?: string;\n\n /**\n * Optional full keytip sequence for the overflow button, if it will have a keytip.\n */\n keytipSequences?: string[];\n\n /**\n * Function that will take in an IOverflowSetItemProps and return the subMenu for that item.\n * If not provided, will use 'item.subMenuProps.items' by default.\n * Alternatively accepts a boolean, return True if the item has a menu and False if not\n * This is only used if your overflow set has keytips.\n */\n itemSubMenuProvider?: (item: IOverflowSetItemProps) => any[] | boolean | undefined;\n\n /**\n * Call to provide customized styling that will layer on top of the variant rules.\n */\n styles?: IStyleFunctionOrObject<IOverflowSetProps, IOverflowSetStyles>;\n}\n\n/**\n * {@docCategory OverflowSet}\n */\nexport interface IOverflowSetStyles {\n /** The style that is layered onto the root element of OverflowSet. */\n root?: IStyle;\n /** The style that is layered onto each individual item in the overflow set. */\n item?: IStyle;\n /** The style that is layered onto the overflow button for the overflow set. */\n overflowButton?: IStyle;\n}\n\n/**\n * The props needed to construct styles.\n * This represents the simplified set of immutable things which control the class names.\n * {@docCategory OverflowSet}\n */\nexport type IOverflowSetStyleProps = Pick<IOverflowSetProps, 'vertical' | 'className'>;\n\n/**\n * {@docCategory OverflowSet}\n */\nexport interface IOverflowSetItemProps {\n /**\n * Unique id to identify the item.\n */\n key: string;\n\n /**\n * Optional keytip for the overflowSetItem.\n */\n keytipProps?: IKeytipProps;\n\n /**\n * Any additional properties to use when custom rendering menu items.\n */\n [propertyName: string]: any;\n}\n"]}
+3
View File
@@ -0,0 +1,3 @@
export * from './OverflowSet';
export * from './OverflowSet.base';
export * from './OverflowSet.types';
+4
View File
@@ -0,0 +1,4 @@
export * from './OverflowSet';
export * from './OverflowSet.base';
export * from './OverflowSet.types';
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"../src/","sources":["components/OverflowSet/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC","sourcesContent":["export * from './OverflowSet';\nexport * from './OverflowSet.base';\nexport * from './OverflowSet.types';\n"]}