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,54 @@
import * as React from 'react';
import { Sticky } from '../../Sticky';
import type { IScrollablePane, IScrollablePaneProps } from './ScrollablePane.types';
import type { JSXElement } from '@fluentui/utilities';
export interface IScrollablePaneState {
stickyTopHeight: number;
stickyBottomHeight: number;
scrollbarWidth: number;
scrollbarHeight: number;
}
export declare class ScrollablePaneBase extends React.Component<IScrollablePaneProps, IScrollablePaneState> implements IScrollablePane {
static contextType: React.Context<import("@fluentui/react-window-provider").WindowProviderProps>;
context: any;
private _root;
private _stickyAboveRef;
private _stickyBelowRef;
private _contentContainer;
private _subscribers;
private _stickies;
private _mutationObserver;
private _notifyThrottled;
private _async;
private _events;
constructor(props: IScrollablePaneProps);
get root(): HTMLDivElement | null;
get stickyAbove(): HTMLDivElement | null;
get stickyBelow(): HTMLDivElement | null;
get contentContainer(): HTMLDivElement | null;
componentDidMount(): void;
componentWillUnmount(): void;
shouldComponentUpdate(nextProps: IScrollablePaneProps, nextState: IScrollablePaneState): boolean;
componentDidUpdate(prevProps: IScrollablePaneProps, prevState: IScrollablePaneState): void;
render(): JSXElement;
setStickiesDistanceFromTop(): void;
forceLayoutUpdate(): void;
subscribe: (handler: Function) => void;
unsubscribe: (handler: Function) => void;
addSticky: (sticky: Sticky) => void;
removeSticky: (sticky: Sticky) => void;
sortSticky: (sticky: Sticky, sortAgain?: boolean) => void;
updateStickyRefHeights: () => void;
notifySubscribers: () => void;
getScrollPosition: () => number;
syncScrollSticky: (sticky: Sticky) => void;
private _getScrollablePaneContext;
private _checkStickyStatus;
private _addToStickyContainer;
private _removeStickyFromContainers;
private _onWindowResize;
private _getStickyContainerStyle;
private _getScrollbarWidth;
private _getScrollbarHeight;
private _onScroll;
}
@@ -0,0 +1,407 @@
import { __assign, __extends } from "tslib";
import * as React from 'react';
import { Async, EventGroup, classNamesFunction, divProperties, getNativeProps, getRTL, initializeComponentRef, } from '../../Utilities';
import { ScrollablePaneContext } from './ScrollablePane.types';
import { WindowContext } from '@fluentui/react-window-provider';
import { getWindowEx } from '../../utilities/dom';
var getClassNames = classNamesFunction();
var ScrollablePaneBase = /** @class */ (function (_super) {
__extends(ScrollablePaneBase, _super);
function ScrollablePaneBase(props) {
var _this = _super.call(this, props) || this;
_this._root = React.createRef();
_this._stickyAboveRef = React.createRef();
_this._stickyBelowRef = React.createRef();
_this._contentContainer = React.createRef();
_this.subscribe = function (handler) {
_this._subscribers.add(handler);
};
_this.unsubscribe = function (handler) {
_this._subscribers.delete(handler);
};
_this.addSticky = function (sticky) {
_this._stickies.add(sticky);
// If ScrollablePane is mounted, then sort sticky in correct place
if (_this.contentContainer) {
sticky.setDistanceFromTop(_this.contentContainer);
_this.sortSticky(sticky);
}
};
_this.removeSticky = function (sticky) {
_this._stickies.delete(sticky);
_this._removeStickyFromContainers(sticky);
_this.notifySubscribers();
};
_this.sortSticky = function (sticky, sortAgain) {
if (_this.stickyAbove && _this.stickyBelow) {
if (sortAgain) {
_this._removeStickyFromContainers(sticky);
}
if (sticky.canStickyTop && sticky.stickyContentTop) {
_this._addToStickyContainer(sticky, _this.stickyAbove, sticky.stickyContentTop);
}
if (sticky.canStickyBottom && sticky.stickyContentBottom) {
_this._addToStickyContainer(sticky, _this.stickyBelow, sticky.stickyContentBottom);
}
}
};
_this.updateStickyRefHeights = function () {
var stickyItems = _this._stickies;
var stickyTopHeight = 0;
var stickyBottomHeight = 0;
stickyItems.forEach(function (sticky) {
var _a = sticky.state, isStickyTop = _a.isStickyTop, isStickyBottom = _a.isStickyBottom;
if (sticky.nonStickyContent) {
if (isStickyTop) {
stickyTopHeight += sticky.nonStickyContent.offsetHeight;
}
if (isStickyBottom) {
stickyBottomHeight += sticky.nonStickyContent.offsetHeight;
}
_this._checkStickyStatus(sticky);
}
});
_this.setState({
stickyTopHeight: stickyTopHeight,
stickyBottomHeight: stickyBottomHeight,
});
};
_this.notifySubscribers = function () {
if (_this.contentContainer) {
_this._subscribers.forEach(function (handle) {
// this.stickyBelow is passed in for calculating distance to determine Sticky status
handle(_this.contentContainer, _this.stickyBelow);
});
}
};
_this.getScrollPosition = function () {
if (_this.contentContainer) {
return _this.contentContainer.scrollTop;
}
return 0;
};
_this.syncScrollSticky = function (sticky) {
if (sticky && _this.contentContainer) {
sticky.syncScroll(_this.contentContainer);
}
};
_this._getScrollablePaneContext = function () {
return {
scrollablePane: {
subscribe: _this.subscribe,
unsubscribe: _this.unsubscribe,
addSticky: _this.addSticky,
removeSticky: _this.removeSticky,
updateStickyRefHeights: _this.updateStickyRefHeights,
sortSticky: _this.sortSticky,
notifySubscribers: _this.notifySubscribers,
syncScrollSticky: _this.syncScrollSticky,
},
window: getWindowEx(_this.context),
};
};
_this._addToStickyContainer = function (sticky, stickyContainer, stickyContentToAdd) {
// If there's no children, append child to list, otherwise, sort though array and append at correct position
if (!stickyContainer.children.length) {
stickyContainer.appendChild(stickyContentToAdd);
}
else {
// If stickyContentToAdd isn't a child element of target container, then append
if (!stickyContainer.contains(stickyContentToAdd)) {
var stickyChildrenElements_1 = [].slice.call(stickyContainer.children);
var stickyList_1 = [];
// Get stickies. Filter by canStickyTop/Bottom, then sort by distance from top, and then
// filter by elements that are in the stickyContainer already.
_this._stickies.forEach(function (stickyItem) {
if (stickyContainer === _this.stickyAbove && sticky.canStickyTop) {
stickyList_1.push(stickyItem);
}
else if (sticky.canStickyBottom) {
stickyList_1.push(stickyItem);
}
});
var stickyListSorted = stickyList_1
.sort(function (a, b) {
return (a.state.distanceFromTop || 0) - (b.state.distanceFromTop || 0);
})
.filter(function (item) {
var stickyContent = stickyContainer === _this.stickyAbove ? item.stickyContentTop : item.stickyContentBottom;
if (stickyContent) {
return stickyChildrenElements_1.indexOf(stickyContent) > -1;
}
return false;
});
// Get first element that has a distance from top that is further than our sticky that is being added
var targetStickyToAppendBefore = undefined;
for (var _i = 0, stickyListSorted_1 = stickyListSorted; _i < stickyListSorted_1.length; _i++) {
var stickyListItem = stickyListSorted_1[_i];
if ((stickyListItem.state.distanceFromTop || 0) >= (sticky.state.distanceFromTop || 0)) {
targetStickyToAppendBefore = stickyListItem;
break;
}
}
// If target element to append before is known, grab respective stickyContentTop/Bottom element
// and insert before
var targetContainer = null;
if (targetStickyToAppendBefore) {
targetContainer =
stickyContainer === _this.stickyAbove
? targetStickyToAppendBefore.stickyContentTop
: targetStickyToAppendBefore.stickyContentBottom;
}
stickyContainer.insertBefore(stickyContentToAdd, targetContainer);
}
}
};
_this._removeStickyFromContainers = function (sticky) {
if (_this.stickyAbove && sticky.stickyContentTop && _this.stickyAbove.contains(sticky.stickyContentTop)) {
_this.stickyAbove.removeChild(sticky.stickyContentTop);
}
if (_this.stickyBelow && sticky.stickyContentBottom && _this.stickyBelow.contains(sticky.stickyContentBottom)) {
_this.stickyBelow.removeChild(sticky.stickyContentBottom);
}
};
_this._onWindowResize = function () {
var scrollbarWidth = _this._getScrollbarWidth();
var scrollbarHeight = _this._getScrollbarHeight();
_this.setState({
scrollbarWidth: scrollbarWidth,
scrollbarHeight: scrollbarHeight,
});
_this.notifySubscribers();
};
_this._getStickyContainerStyle = function (height, isTop) {
return __assign(__assign({ height: height }, (getRTL(_this.props.theme)
? {
right: '0',
left: "".concat(_this.state.scrollbarWidth || _this._getScrollbarWidth() || 0, "px"),
}
: {
left: '0',
right: "".concat(_this.state.scrollbarWidth || _this._getScrollbarWidth() || 0, "px"),
})), (isTop
? {
top: '0',
}
: {
bottom: "".concat(_this.state.scrollbarHeight || _this._getScrollbarHeight() || 0, "px"),
}));
};
_this._onScroll = function () {
var contentContainer = _this.contentContainer;
if (contentContainer) {
_this._stickies.forEach(function (sticky) {
sticky.syncScroll(contentContainer);
});
}
_this._notifyThrottled();
};
_this._subscribers = new Set();
_this._stickies = new Set();
initializeComponentRef(_this);
_this.state = {
stickyTopHeight: 0,
stickyBottomHeight: 0,
scrollbarWidth: 0,
scrollbarHeight: 0,
};
return _this;
}
Object.defineProperty(ScrollablePaneBase.prototype, "root", {
get: function () {
return this._root.current;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ScrollablePaneBase.prototype, "stickyAbove", {
get: function () {
return this._stickyAboveRef.current;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ScrollablePaneBase.prototype, "stickyBelow", {
get: function () {
return this._stickyBelowRef.current;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ScrollablePaneBase.prototype, "contentContainer", {
get: function () {
return this._contentContainer.current;
},
enumerable: false,
configurable: true
});
ScrollablePaneBase.prototype.componentDidMount = function () {
var _this = this;
var win = getWindowEx(this.context);
var initialScrollPosition = this.props.initialScrollPosition;
this._async = new Async(this);
this._notifyThrottled = this._async.throttle(this.notifySubscribers, 50);
this._events = new EventGroup(this);
this._events.on(this.contentContainer, 'scroll', this._onScroll);
this._events.on(win, 'resize', this._onWindowResize);
if (this.contentContainer && initialScrollPosition) {
this.contentContainer.scrollTop = initialScrollPosition;
}
// Set sticky distances from top property, then sort in correct order and notify subscribers
this.setStickiesDistanceFromTop();
this._stickies.forEach(function (sticky) {
_this.sortSticky(sticky);
});
this.notifySubscribers();
if (win && 'MutationObserver' in win) {
this._mutationObserver = new MutationObserver(function (mutation) {
// Function to check if mutation is occuring in stickyAbove or stickyBelow
function checkIfMutationIsSticky(mutationRecord) {
if (this.stickyAbove !== null && this.stickyBelow !== null) {
return this.stickyAbove.contains(mutationRecord.target) || this.stickyBelow.contains(mutationRecord.target);
}
return false;
}
// Compute the scrollbar height, which might have changed if the content's width changed and caused overflow
var scrollbarHeight = _this._getScrollbarHeight();
// If the scrollbar height changed, update state so it's postioned correctly below sticky footer
if (scrollbarHeight !== _this.state.scrollbarHeight) {
_this.setState({
scrollbarHeight: scrollbarHeight,
});
}
// Notify subscribers again to re-check whether Sticky should be Sticky'd or not
_this.notifySubscribers();
// If mutation occurs in sticky header or footer, then update sticky top/bottom heights
if (mutation.some(checkIfMutationIsSticky.bind(_this))) {
_this.updateStickyRefHeights();
}
else {
// If mutation occurs in scrollable region, then find Sticky it belongs to and force update
var stickyList_2 = [];
_this._stickies.forEach(function (sticky) {
if (sticky.root && sticky.root.contains(mutation[0].target)) {
stickyList_2.push(sticky);
}
});
if (stickyList_2.length) {
stickyList_2.forEach(function (sticky) {
sticky.forceUpdate();
});
}
}
});
if (this.root) {
this._mutationObserver.observe(this.root, {
childList: true,
attributes: true,
subtree: true,
characterData: true,
});
}
}
};
ScrollablePaneBase.prototype.componentWillUnmount = function () {
this._events.dispose();
this._async.dispose();
if (this._mutationObserver) {
this._mutationObserver.disconnect();
}
};
// Only updates if props/state change, just to prevent excessive setState with updateStickyRefHeights
ScrollablePaneBase.prototype.shouldComponentUpdate = function (nextProps, nextState) {
return (this.props.children !== nextProps.children ||
this.props.initialScrollPosition !== nextProps.initialScrollPosition ||
this.props.className !== nextProps.className ||
this.state.stickyTopHeight !== nextState.stickyTopHeight ||
this.state.stickyBottomHeight !== nextState.stickyBottomHeight ||
this.state.scrollbarWidth !== nextState.scrollbarWidth ||
this.state.scrollbarHeight !== nextState.scrollbarHeight);
};
ScrollablePaneBase.prototype.componentDidUpdate = function (prevProps, prevState) {
var initialScrollPosition = this.props.initialScrollPosition;
if (this.contentContainer &&
typeof initialScrollPosition === 'number' &&
prevProps.initialScrollPosition !== initialScrollPosition) {
this.contentContainer.scrollTop = initialScrollPosition;
}
// Update subscribers when stickyTopHeight/stickyBottomHeight changes
if (prevState.stickyTopHeight !== this.state.stickyTopHeight ||
prevState.stickyBottomHeight !== this.state.stickyBottomHeight) {
this.notifySubscribers();
}
this._async.setTimeout(this._onWindowResize, 0);
};
ScrollablePaneBase.prototype.render = function () {
var _a = this.props, className = _a.className, scrollContainerFocus = _a.scrollContainerFocus, scrollContainerAriaLabel = _a.scrollContainerAriaLabel, theme = _a.theme, styles = _a.styles, onScroll = _a.onScroll;
var _b = this.state, stickyTopHeight = _b.stickyTopHeight, stickyBottomHeight = _b.stickyBottomHeight;
var classNames = getClassNames(styles, {
theme: theme,
className: className,
scrollbarVisibility: this.props.scrollbarVisibility,
});
var scrollContainerProps = scrollContainerFocus
? {
role: 'group',
tabIndex: 0,
'aria-label': scrollContainerAriaLabel,
onScroll: onScroll,
}
: {
onScroll: onScroll,
};
return (React.createElement("div", __assign({}, getNativeProps(__assign({}, this.props), divProperties,
// on React 17 onScroll is not being invoked on root element,
// as a fix this method will be provided to the container element
['onScroll']), { ref: this._root, className: classNames.root }),
React.createElement("div", { ref: this._stickyAboveRef, className: classNames.stickyAbove, style: this._getStickyContainerStyle(stickyTopHeight, true) }),
React.createElement("div", __assign({ ref: this._contentContainer }, scrollContainerProps, { className: classNames.contentContainer, "data-is-scrollable": true }),
React.createElement(ScrollablePaneContext.Provider, { value: this._getScrollablePaneContext() }, this.props.children)),
React.createElement("div", { className: classNames.stickyBelow, style: this._getStickyContainerStyle(stickyBottomHeight, false) },
React.createElement("div", { ref: this._stickyBelowRef, className: classNames.stickyBelowItems }))));
};
ScrollablePaneBase.prototype.setStickiesDistanceFromTop = function () {
var _this = this;
if (this.contentContainer) {
this._stickies.forEach(function (sticky) {
sticky.setDistanceFromTop(_this.contentContainer);
});
}
};
ScrollablePaneBase.prototype.forceLayoutUpdate = function () {
this._onWindowResize();
};
ScrollablePaneBase.prototype._checkStickyStatus = function (sticky) {
if (this.stickyAbove && this.stickyBelow && this.contentContainer && sticky.nonStickyContent) {
// If sticky is sticky, then append content to appropriate container
if (sticky.state.isStickyTop || sticky.state.isStickyBottom) {
if (sticky.state.isStickyTop &&
!this.stickyAbove.contains(sticky.nonStickyContent) &&
sticky.stickyContentTop) {
sticky.addSticky(sticky.stickyContentTop);
}
if (sticky.state.isStickyBottom &&
!this.stickyBelow.contains(sticky.nonStickyContent) &&
sticky.stickyContentBottom) {
sticky.addSticky(sticky.stickyContentBottom);
}
}
else if (!this.contentContainer.contains(sticky.nonStickyContent)) {
// Reset sticky if it's not sticky and not in the contentContainer element
sticky.resetSticky();
}
}
};
ScrollablePaneBase.prototype._getScrollbarWidth = function () {
var contentContainer = this.contentContainer;
return contentContainer ? contentContainer.offsetWidth - contentContainer.clientWidth : 0;
};
ScrollablePaneBase.prototype._getScrollbarHeight = function () {
var contentContainer = this.contentContainer;
return contentContainer ? contentContainer.offsetHeight - contentContainer.clientHeight : 0;
};
ScrollablePaneBase.contextType = WindowContext;
return ScrollablePaneBase;
}(React.Component));
export { ScrollablePaneBase };
//# sourceMappingURL=ScrollablePane.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 { IScrollablePaneProps } from './ScrollablePane.types';
export declare const ScrollablePane: React.FunctionComponent<IScrollablePaneProps>;
@@ -0,0 +1,5 @@
import { getStyles } from './ScrollablePane.styles';
import { ScrollablePaneBase } from './ScrollablePane.base';
import { styled } from '../../Utilities';
export var ScrollablePane = styled(ScrollablePaneBase, getStyles, undefined, { scope: 'ScrollablePane' });
//# sourceMappingURL=ScrollablePane.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ScrollablePane.js","sourceRoot":"../src/","sources":["components/ScrollablePane/ScrollablePane.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAGzC,MAAM,CAAC,IAAM,cAAc,GAAkD,MAAM,CAIjF,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC","sourcesContent":["import * as React from 'react';\nimport { getStyles } from './ScrollablePane.styles';\nimport { ScrollablePaneBase } from './ScrollablePane.base';\nimport { styled } from '../../Utilities';\nimport type { IScrollablePaneProps, IScrollablePaneStyleProps, IScrollablePaneStyles } from './ScrollablePane.types';\n\nexport const ScrollablePane: React.FunctionComponent<IScrollablePaneProps> = styled<\n IScrollablePaneProps,\n IScrollablePaneStyleProps,\n IScrollablePaneStyles\n>(ScrollablePaneBase, getStyles, undefined, { scope: 'ScrollablePane' });\n"]}
@@ -0,0 +1,3 @@
export declare const root = "root_cf619380";
export declare const stickyAbove = "stickyAbove_cf619380";
export declare const stickyBelow = "stickyBelow_cf619380";
@@ -0,0 +1,7 @@
/* eslint-disable */
import { loadStyles } from '@microsoft/load-themed-styles';
loadStyles([{ "rawString": ".root_cf619380{overflow-y:auto;max-height:inherit;height:inherit;-webkit-overflow-scrolling:touch}.stickyAbove_cf619380,.stickyBelow_cf619380{position:absolute;pointer-events:auto;width:100%;z-index:1}.stickyAbove_cf619380{top:0}@media screen and (-ms-high-contrast:active),screen and (forced-colors:active){.stickyAbove_cf619380{border-bottom:1px solid WindowText}}.stickyBelow_cf619380{bottom:0}@media screen and (-ms-high-contrast:active),screen and (forced-colors:active){.stickyBelow_cf619380{border-top:1px solid WindowText}}" }]);
export var root = "root_cf619380";
export var stickyAbove = "stickyAbove_cf619380";
export var stickyBelow = "stickyBelow_cf619380";
//# sourceMappingURL=ScrollablePane.scss.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ScrollablePane.scss.js","sourceRoot":"../src/","sources":["components/ScrollablePane/ScrollablePane.scss.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,UAAU,CAAC,CAAC,EAAC,WAAW,EAAC,qhBAAqhB,EAAC,CAAC,CAAC,CAAC;AACljB,MAAM,CAAC,IAAM,IAAI,GAAG,eAAe,CAAC;AACpC,MAAM,CAAC,IAAM,WAAW,GAAG,sBAAsB,CAAC;AAClD,MAAM,CAAC,IAAM,WAAW,GAAG,sBAAsB,CAAC","sourcesContent":["/* eslint-disable */\nimport { loadStyles } from '@microsoft/load-themed-styles';\nloadStyles([{\"rawString\":\".root_cf619380{overflow-y:auto;max-height:inherit;height:inherit;-webkit-overflow-scrolling:touch}.stickyAbove_cf619380,.stickyBelow_cf619380{position:absolute;pointer-events:auto;width:100%;z-index:1}.stickyAbove_cf619380{top:0}@media screen and (-ms-high-contrast:active),screen and (forced-colors:active){.stickyAbove_cf619380{border-bottom:1px solid WindowText}}.stickyBelow_cf619380{bottom:0}@media screen and (-ms-high-contrast:active),screen and (forced-colors:active){.stickyBelow_cf619380{border-top:1px solid WindowText}}\"}]);\nexport const root = \"root_cf619380\";\nexport const stickyAbove = \"stickyAbove_cf619380\";\nexport const stickyBelow = \"stickyBelow_cf619380\";"]}
@@ -0,0 +1,2 @@
import type { IScrollablePaneStyleProps, IScrollablePaneStyles } from './ScrollablePane.types';
export declare const getStyles: (props: IScrollablePaneStyleProps) => IScrollablePaneStyles;
@@ -0,0 +1,65 @@
import { HighContrastSelector, getGlobalClassNames } from '../../Styling';
var GlobalClassNames = {
root: 'ms-ScrollablePane',
contentContainer: 'ms-ScrollablePane--contentContainer',
};
export var getStyles = function (props) {
var _a, _b;
var className = props.className, theme = props.theme;
var classNames = getGlobalClassNames(GlobalClassNames, theme);
var AboveAndBelowStyles = {
position: 'absolute',
pointerEvents: 'none',
};
var positioningStyle = {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
WebkitOverflowScrolling: 'touch',
};
return {
root: [classNames.root, theme.fonts.medium, positioningStyle, className],
contentContainer: [
classNames.contentContainer,
{
overflowY: props.scrollbarVisibility === 'always' ? 'scroll' : 'auto',
},
positioningStyle,
],
stickyAbove: [
{
top: 0,
zIndex: 1,
selectors: (_a = {},
_a[HighContrastSelector] = {
borderBottom: '1px solid WindowText',
},
_a),
},
AboveAndBelowStyles,
],
stickyBelow: [
{
bottom: 0,
selectors: (_b = {},
_b[HighContrastSelector] = {
borderTop: '1px solid WindowText',
},
_b),
},
AboveAndBelowStyles,
],
stickyBelowItems: [
{
bottom: 0,
},
AboveAndBelowStyles,
{
width: '100%',
},
],
};
};
//# sourceMappingURL=ScrollablePane.styles.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ScrollablePane.styles.js","sourceRoot":"../src/","sources":["components/ScrollablePane/ScrollablePane.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAI1E,IAAM,gBAAgB,GAAG;IACvB,IAAI,EAAE,mBAAmB;IACzB,gBAAgB,EAAE,qCAAqC;CACxD,CAAC;AAEF,MAAM,CAAC,IAAM,SAAS,GAAG,UAAC,KAAgC;;IAChD,IAAA,SAAS,GAAY,KAAK,UAAjB,EAAE,KAAK,GAAK,KAAK,MAAV,CAAW;IAEnC,IAAM,UAAU,GAAG,mBAAmB,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAEhE,IAAM,mBAAmB,GAAW;QAClC,QAAQ,EAAE,UAAU;QACpB,aAAa,EAAE,MAAM;KACtB,CAAC;IAEF,IAAM,gBAAgB,GAAW;QAC/B,QAAQ,EAAE,UAAU;QACpB,GAAG,EAAE,CAAC;QACN,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,IAAI,EAAE,CAAC;QACP,uBAAuB,EAAE,OAAO;KACjC,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,SAAS,CAAC;QACxE,gBAAgB,EAAE;YAChB,UAAU,CAAC,gBAAgB;YAC3B;gBACE,SAAS,EAAE,KAAK,CAAC,mBAAmB,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM;aACtE;YACD,gBAAgB;SACjB;QACD,WAAW,EAAE;YACX;gBACE,GAAG,EAAE,CAAC;gBACN,MAAM,EAAE,CAAC;gBACT,SAAS;oBACP,GAAC,oBAAoB,IAAG;wBACtB,YAAY,EAAE,sBAAsB;qBACrC;uBACF;aACF;YACD,mBAAmB;SACpB;QACD,WAAW,EAAE;YACX;gBACE,MAAM,EAAE,CAAC;gBACT,SAAS;oBACP,GAAC,oBAAoB,IAAG;wBACtB,SAAS,EAAE,sBAAsB;qBAClC;uBACF;aACF;YACD,mBAAmB;SACpB;QACD,gBAAgB,EAAE;YAChB;gBACE,MAAM,EAAE,CAAC;aACV;YACD,mBAAmB;YACnB;gBACE,KAAK,EAAE,MAAM;aACd;SACF;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { HighContrastSelector, getGlobalClassNames } from '../../Styling';\nimport type { IScrollablePaneStyleProps, IScrollablePaneStyles } from './ScrollablePane.types';\nimport type { IStyle } from '../../Styling';\n\nconst GlobalClassNames = {\n root: 'ms-ScrollablePane',\n contentContainer: 'ms-ScrollablePane--contentContainer',\n};\n\nexport const getStyles = (props: IScrollablePaneStyleProps): IScrollablePaneStyles => {\n const { className, theme } = props;\n\n const classNames = getGlobalClassNames(GlobalClassNames, theme);\n\n const AboveAndBelowStyles: IStyle = {\n position: 'absolute',\n pointerEvents: 'none',\n };\n\n const positioningStyle: IStyle = {\n position: 'absolute',\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n WebkitOverflowScrolling: 'touch',\n };\n\n return {\n root: [classNames.root, theme.fonts.medium, positioningStyle, className],\n contentContainer: [\n classNames.contentContainer,\n {\n overflowY: props.scrollbarVisibility === 'always' ? 'scroll' : 'auto',\n },\n positioningStyle,\n ],\n stickyAbove: [\n {\n top: 0,\n zIndex: 1,\n selectors: {\n [HighContrastSelector]: {\n borderBottom: '1px solid WindowText',\n },\n },\n },\n AboveAndBelowStyles,\n ],\n stickyBelow: [\n {\n bottom: 0,\n selectors: {\n [HighContrastSelector]: {\n borderTop: '1px solid WindowText',\n },\n },\n },\n AboveAndBelowStyles,\n ],\n stickyBelowItems: [\n {\n bottom: 0,\n },\n AboveAndBelowStyles,\n {\n width: '100%',\n },\n ],\n };\n};\n"]}
@@ -0,0 +1,116 @@
import * as React from 'react';
import { ScrollablePaneBase } from './ScrollablePane.base';
import { Sticky } from '../Sticky/Sticky';
import type { IRefObject, IStyleFunctionOrObject } from '../../Utilities';
import type { IStyle, ITheme } from '../../Styling';
/**
* {@docCategory ScrollablePane}
*/
export interface IScrollablePane {
/** Triggers a layout update for the pane. */
forceLayoutUpdate(): void;
/** Gets the current scroll position of the scrollable pane */
getScrollPosition(): number;
}
/**
* {@docCategory ScrollablePane}
*/
export interface IScrollablePaneProps extends React.HTMLAttributes<HTMLElement | ScrollablePaneBase> {
/**
* Optional callback to access the IScrollablePane interface. Use this instead of ref for accessing
* the public methods and properties of the component.
*/
componentRef?: IRefObject<IScrollablePane>;
/**
* Call to provide customized styling that will layer on top of the variant rules
*/
styles?: IStyleFunctionOrObject<IScrollablePaneStyleProps, IScrollablePaneStyles>;
/**
* Theme provided by HOC.
*/
theme?: ITheme;
/**
* Additional css class to apply to the ScrollablePane
* @defaultvalue undefined
*/
className?: string;
/**
* Sets the initial scroll position of the ScrollablePane
*/
initialScrollPosition?: number;
scrollbarVisibility?: ScrollbarVisibility;
/**
* Makes the scrollable container focusable, to aid with keyboard-only scrolling
* Should only be set to true if the scrollable region will not contain any other focusable items
* @defaultvalue false
*/
scrollContainerFocus?: boolean;
/**
* If scrollContainerFocus is set to true, use this to give the container an accessible name
*/
scrollContainerAriaLabel?: string;
}
/**
* {@docCategory ScrollablePane}
*/
export interface IScrollablePaneStyleProps {
/**
* Accept theme prop.
*/
theme: ITheme;
/**
* Accept custom classNames
*/
className?: string;
scrollbarVisibility?: IScrollablePaneProps['scrollbarVisibility'];
}
/**
* {@docCategory ScrollablePane}
*/
export interface IScrollablePaneStyles {
/**
* Style set for the root element.
*/
root: IStyle;
/**
* Style set for the stickyAbove element.
*/
stickyAbove: IStyle;
/**
* Style set for the stickyBelow element.
*/
stickyBelow: IStyle;
/**
* Style set for the stickyBelowItems element.
*/
stickyBelowItems: IStyle;
/**
* Style set for the contentContainer element.
*/
contentContainer: IStyle;
}
/**
* {@docCategory ScrollablePane}
*/
export declare const ScrollbarVisibility: {
auto: "auto";
always: "always";
};
/**
* {@docCategory ScrollablePane}
*/
export type ScrollbarVisibility = (typeof ScrollbarVisibility)[keyof typeof ScrollbarVisibility];
export interface IScrollablePaneContext {
scrollablePane?: {
subscribe: (handler: (container: HTMLElement, stickyContainer: HTMLElement) => void) => void;
unsubscribe: (handler: (container: HTMLElement, stickyContainer: HTMLElement) => void) => void;
addSticky: (sticky: Sticky) => void;
removeSticky: (sticky: Sticky) => void;
updateStickyRefHeights: () => void;
sortSticky: (sticky: Sticky, sortAgain?: boolean) => void;
notifySubscribers: (sort?: boolean) => void;
syncScrollSticky: (sticky: Sticky) => void;
};
window: Window | undefined;
}
export declare const ScrollablePaneContext: React.Context<IScrollablePaneContext>;
@@ -0,0 +1,13 @@
import * as React from 'react';
/**
* {@docCategory ScrollablePane}
*/
export var ScrollbarVisibility = {
auto: 'auto',
always: 'always',
};
export var ScrollablePaneContext = React.createContext({
scrollablePane: undefined,
window: undefined,
});
//# sourceMappingURL=ScrollablePane.types.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ScrollablePane.types.js","sourceRoot":"../src/","sources":["components/ScrollablePane/ScrollablePane.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA4G/B;;GAEG;AACH,MAAM,CAAC,IAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,MAAgB;IACtB,MAAM,EAAE,QAAoB;CAC7B,CAAC;AAqBF,MAAM,CAAC,IAAM,qBAAqB,GAAG,KAAK,CAAC,aAAa,CAAyB;IAC/E,cAAc,EAAE,SAAS;IACzB,MAAM,EAAE,SAAS;CAClB,CAAC,CAAC","sourcesContent":["import * as React from 'react';\nimport { ScrollablePaneBase } from './ScrollablePane.base';\nimport { Sticky } from '../Sticky/Sticky';\nimport type { IRefObject, IStyleFunctionOrObject } from '../../Utilities';\nimport type { IStyle, ITheme } from '../../Styling';\n\n/**\n * {@docCategory ScrollablePane}\n */\nexport interface IScrollablePane {\n /** Triggers a layout update for the pane. */\n forceLayoutUpdate(): void;\n /** Gets the current scroll position of the scrollable pane */\n getScrollPosition(): number;\n}\n\n/**\n * {@docCategory ScrollablePane}\n */\nexport interface IScrollablePaneProps extends React.HTMLAttributes<HTMLElement | ScrollablePaneBase> {\n // export interface IScrollablePaneProps extends IReactProps<ScrollablePaneBase> {\n /**\n * Optional callback to access the IScrollablePane interface. Use this instead of ref for accessing\n * the public methods and properties of the component.\n */\n componentRef?: IRefObject<IScrollablePane>;\n\n /**\n * Call to provide customized styling that will layer on top of the variant rules\n */\n styles?: IStyleFunctionOrObject<IScrollablePaneStyleProps, IScrollablePaneStyles>;\n\n /**\n * Theme provided by HOC.\n */\n theme?: ITheme;\n\n /**\n * Additional css class to apply to the ScrollablePane\n * @defaultvalue undefined\n */\n className?: string;\n\n /**\n * Sets the initial scroll position of the ScrollablePane\n */\n initialScrollPosition?: number;\n\n scrollbarVisibility?: ScrollbarVisibility;\n\n /**\n * Makes the scrollable container focusable, to aid with keyboard-only scrolling\n * Should only be set to true if the scrollable region will not contain any other focusable items\n * @defaultvalue false\n */\n scrollContainerFocus?: boolean;\n\n /**\n * If scrollContainerFocus is set to true, use this to give the container an accessible name\n */\n scrollContainerAriaLabel?: string;\n}\n\n/**\n * {@docCategory ScrollablePane}\n */\nexport interface IScrollablePaneStyleProps {\n /**\n * Accept theme prop.\n */\n theme: ITheme;\n\n /**\n * Accept custom classNames\n */\n className?: string;\n\n scrollbarVisibility?: IScrollablePaneProps['scrollbarVisibility'];\n\n // Insert ScrollablePane style props below\n}\n\n/**\n * {@docCategory ScrollablePane}\n */\nexport interface IScrollablePaneStyles {\n /**\n * Style set for the root element.\n */\n root: IStyle;\n /**\n * Style set for the stickyAbove element.\n */\n stickyAbove: IStyle;\n /**\n * Style set for the stickyBelow element.\n */\n stickyBelow: IStyle;\n /**\n * Style set for the stickyBelowItems element.\n */\n stickyBelowItems: IStyle;\n /**\n * Style set for the contentContainer element.\n */\n contentContainer: IStyle;\n}\n\n/**\n * {@docCategory ScrollablePane}\n */\nexport const ScrollbarVisibility = {\n auto: 'auto' as 'auto',\n always: 'always' as 'always',\n};\n\n/**\n * {@docCategory ScrollablePane}\n */\nexport type ScrollbarVisibility = (typeof ScrollbarVisibility)[keyof typeof ScrollbarVisibility];\n\nexport interface IScrollablePaneContext {\n scrollablePane?: {\n subscribe: (handler: (container: HTMLElement, stickyContainer: HTMLElement) => void) => void;\n unsubscribe: (handler: (container: HTMLElement, stickyContainer: HTMLElement) => void) => void;\n addSticky: (sticky: Sticky) => void;\n removeSticky: (sticky: Sticky) => void;\n updateStickyRefHeights: () => void;\n sortSticky: (sticky: Sticky, sortAgain?: boolean) => void;\n notifySubscribers: (sort?: boolean) => void;\n syncScrollSticky: (sticky: Sticky) => void;\n };\n window: Window | undefined;\n}\n\nexport const ScrollablePaneContext = React.createContext<IScrollablePaneContext>({\n scrollablePane: undefined,\n window: undefined,\n});\n"]}
@@ -0,0 +1,3 @@
export * from './ScrollablePane';
export * from './ScrollablePane.base';
export * from './ScrollablePane.types';
+4
View File
@@ -0,0 +1,4 @@
export * from './ScrollablePane';
export * from './ScrollablePane.base';
export * from './ScrollablePane.types';
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"../src/","sources":["components/ScrollablePane/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC","sourcesContent":["export * from './ScrollablePane';\nexport * from './ScrollablePane.base';\nexport * from './ScrollablePane.types';\n"]}