diff --git a/packages/overlayscrollbars/src/environment.ts b/packages/overlayscrollbars/src/environment.ts index 9302cb1..b0bb3ea 100644 --- a/packages/overlayscrollbars/src/environment.ts +++ b/packages/overlayscrollbars/src/environment.ts @@ -36,6 +36,46 @@ type EnvironmentEventMap = { _: []; }; +/** + * Describes the OverlayScrollbars environment. + */ +export interface Environment { + /** The native scrollbars size of the browser / system. */ + scrollbarsSize: XY; + /** Whether the native scrollbars are overlaid. */ + scrollbarsOverlaid: XY; + /** Whether the browser supports native scrollbars hiding. */ + scrollbarsHiding: boolean; + /** The rtl scroll behavior of the browser. */ + rtlScrollBehavior: { n: boolean; i: boolean }; + /** Whether the browser supports all needed Flexbox features for OverlayScrollbars to work in a more performant way. */ + flexboxGlue: boolean; + /** Whether the browser supports custom css properties. (also known as css variables) */ + cssCustomProperties: boolean; + /** The default Initialization to use if nothing else is specified. */ + staticDefaultInitialization: Initialization; + /** The default Options to use if nothing else is specified. */ + staticDefaultOptions: Options; + + /** Returns the current default Initialization. */ + getDefaultInitialization(): Initialization; + /** Returns the current default Options. */ + getDefaultOptions(): Options; + + /** + * Sets a new default Initialization. + * If the new default Initialization is partially filled, its deeply merged with the current default Initialization. + * @param newDefaultInitialization The new default Initialization. + */ + setDefaultInitialization(newDefaultInitialization: DeepPartial): void; + /** + * Sets new default Options. + * If the new default Options are partially filled, they're deeply merged with the current default Options. + * @param newDefaultOptions The new default Options. + */ + setDefaultOptions(newDefaultOptions: DeepPartial): void; +} + export interface InternalEnvironment { readonly _nativeScrollbarsSize: XY; readonly _nativeScrollbarsOverlaid: XY; diff --git a/packages/overlayscrollbars/src/eventListeners.ts b/packages/overlayscrollbars/src/eventListeners.ts index a7dfb0f..a3837eb 100644 --- a/packages/overlayscrollbars/src/eventListeners.ts +++ b/packages/overlayscrollbars/src/eventListeners.ts @@ -6,38 +6,57 @@ import type { EventListener as GeneralEventListener, } from '~/support/eventListeners'; +/** + * Describes the changes that happend due to an update. + */ export interface OnUpdatedEventListenerArgs { + /** Hints which describe what changed in the DOM. */ updateHints: { + /** Whether the size of the host element changed. */ sizeChanged: boolean; + /** Whether the direction of the host element changed. */ directionChanged: boolean; + /** Whether the intrinsic height behavior changed. */ heightIntrinsicChanged: boolean; + /** Whether the overflow edge (clientWidth / clientHeight) of the viewport element changed. */ overflowEdgeChanged: boolean; + /** Whether the overflow amount changed. */ overflowAmountChanged: boolean; + /** Whether the overflow style changed. */ overflowStyleChanged: boolean; + /** Whether an host mutation took place. */ hostMutation: boolean; + /** Whether an content mutation took place. */ contentMutation: boolean; }; + /** The changed options. */ changedOptions: DeepPartial; + /** Whether the update happened with and force invalidated cache. */ force: boolean; } +/** + * A mapping between event names and their listener arguments. + */ export type EventListenerMap = { - /** - * Triggered after all elements are initialized and appended. - */ + /** Triggered after all elements are initialized and appended. */ initialized: [instance: OverlayScrollbars]; - /** - * Triggered after an update. - */ + /** Triggered after an update. */ updated: [instance: OverlayScrollbars, onUpdatedArgs: OnUpdatedEventListenerArgs]; - /** - * Triggered after all elements, observers and events are destroyed. - */ + /** Triggered after all elements, observers and events are destroyed. */ destroyed: [instance: OverlayScrollbars, canceled: boolean]; }; +/** + * An object which describes the initial event listeners. + * Simplified it looks like: + * { + * [eventName: string]: EventListener | EventListener[] + * } + */ export type InitialEventListeners = GeneralInitialEventListeners; +/** An event listener. */ export type EventListener = GeneralEventListener< EventListenerMap, N diff --git a/packages/overlayscrollbars/src/index.ts b/packages/overlayscrollbars/src/index.ts index 8dae7ac..cf712b8 100644 --- a/packages/overlayscrollbars/src/index.ts +++ b/packages/overlayscrollbars/src/index.ts @@ -6,8 +6,8 @@ export { ScrollbarsHidingPlugin, SizeObserverPlugin, ClickScrollPlugin } from '~ export type { Options, OverflowBehavior, - ScrollbarVisibilityBehavior, - ScrollbarAutoHideBehavior, + ScrollbarsVisibilityBehavior as ScrollbarVisibilityBehavior, + ScrollbarsAutoHideBehavior as ScrollbarAutoHideBehavior, } from '~/options'; export type { EventListenerMap, diff --git a/packages/overlayscrollbars/src/initialization.ts b/packages/overlayscrollbars/src/initialization.ts index 915d11c..6f6990d 100644 --- a/packages/overlayscrollbars/src/initialization.ts +++ b/packages/overlayscrollbars/src/initialization.ts @@ -19,46 +19,84 @@ type FallbackDynamicInitializtationElement = Extract< /** * Static elements are elements which MUST be present in the final DOM. - * With false, null or undefined the element will be generated, otherwise the specified element is taken. + * If an `HTMLElement` is passed the passed element will be taken as the repsective element. + * With `false`, `null` or `undefined` an appropriate element is generated automatically. */ export type StaticInitializationElement = + /** A function which returns the the StaticInitialization value. */ | ((...args: Args) => StaticInitialization) + /** The StaticInitialization value. */ | StaticInitialization; /** - * Dynamic element are elements which CAN be present in the final DOM. - * If its a element the element will be taken as the repsective element. - * With true the element will be generated. - * With false, null or undefined the element won't be generated and wont be in the DOM. + * Dynamic elements are elements which CAN be present in the final DOM. + * If an `HTMLElement`is passed the passed element will be taken as the repsective element. + * With `true` an appropriate element is generated automatically. + * With `false`, `null` or `undefined` the element won't be in the DOM. */ export type DynamicInitializationElement = + /** A function which returns the the DynamicInitialization value. */ | ((...args: Args) => DynamicInitialization) + /** The DynamicInitialization value. */ | DynamicInitialization; +/** + * Describes how a OverlayScrollbar instance should initialize. + */ export type Initialization = { + /** + * Customizes which elements are generated and used. + * If a function is passed to any of the fields, it receives the `target` element as its argument. + */ elements: { - host: StaticInitializationElement<[target: InitializationTargetElement]>; // only relevant for textarea + /** + * Assign a custom element as the host element. + * Only relevant if the target element is a Textarea. + */ + host: StaticInitializationElement<[target: InitializationTargetElement]>; + /** Assign a custom element as the viewport element. */ viewport: StaticInitializationElement<[target: InitializationTargetElement]>; + /** Assign a custom element as the padding element or force the element not to be generated. */ padding: DynamicInitializationElement<[target: InitializationTargetElement]>; + /** Assign a custom element as the content element or force the element not to be generated. */ content: DynamicInitializationElement<[target: InitializationTargetElement]>; }; + /** + * Customizes elements related to the scrollbars. + * If a function is passed, it receives the `target`, `host` and `viewport` element as arguments. + */ scrollbars: { slot: DynamicInitializationElement< [target: InitializationTargetElement, host: HTMLElement, viewport: HTMLElement] >; }; + /** + * Customizes the cancelation behavior. + */ cancel: { + /** Whether the initialization shall be canceled if the native scrollbars are overlaid. */ nativeScrollbarsOverlaid: boolean; + /** + * Whether the initialization shall be canceled if its applied to a body element. + * With `true` an initialization is always canceled, with `false` its never canceled. + * With `null` the initialization will only be canceled when the initialization would affect the browsers functionality. (window.scrollTo, mobile browser behavior etc.) + */ body: boolean | null; }; }; +/** The initialization target element. */ export type InitializationTargetElement = HTMLElement | HTMLTextAreaElement; +/** + * The initialization target object. + * OverlayScrollbars({ target: myElement }) is equivalent to OverlayScrollbars(myElement). + */ export type InitializationTargetObject = DeepPartial & { target: InitializationTargetElement; }; +/** The initialization target. */ export type InitializationTarget = InitializationTargetElement | InitializationTargetObject; const resolveInitialization = (value: any, args: any): T => diff --git a/packages/overlayscrollbars/src/options.ts b/packages/overlayscrollbars/src/options.ts index da4e9b6..e01be48 100644 --- a/packages/overlayscrollbars/src/options.ts +++ b/packages/overlayscrollbars/src/options.ts @@ -18,37 +18,116 @@ const opsStringify = (value: any) => return val; }); +/** + * The overflow behavior of an axis. + */ export type OverflowBehavior = + /** No scrolling is possible and the content is clipped. */ | 'hidden' - | 'scroll' + /** No scrolling is possible and the content isn't clipped. */ | 'visible' + /** Scrolling is possible if there is an overflow. */ + | 'scroll' + /** + * If the other axis has no overflow the behavior is similar to `visible`. + * If the other axis has overflow the behavior is similar to `hidden`. + */ | 'visible-hidden' + /** + * If the other axis has no overflow the behavior is similar to `visible`. + * If the other axis has overflow the behavior is similar to `scroll`. + */ | 'visible-scroll'; -export type ScrollbarVisibilityBehavior = 'visible' | 'hidden' | 'auto'; +/** + * The scrollbars visibility behavior. + */ +export type ScrollbarsVisibilityBehavior = + /** The scrollbars are always visible. */ + | 'visible' + /** The scrollbars are always hidden. */ + | 'hidden' + /** The scrollbars are only visibile if there is overflow. */ + | 'auto'; -export type ScrollbarAutoHideBehavior = 'never' | 'scroll' | 'leave' | 'move'; +/** + * The scrollbars auto hide behavior + */ +export type ScrollbarsAutoHideBehavior = + /** The scrollbars are never hidden automatically. */ + | 'never' + /** The scrollbars are hidden unless the user scrolls. */ + | 'scroll' + /** The scrollbars are hidden unless the pointer moves in the host element or the user scrolls. */ + | 'move' + /** The scrollbars are hidden if the pointer leaves the host element or unless the user scrolls. */ + | 'leave'; +/** + * Describes the options of a OverlayScrollbars instance. + */ export interface Options { + /** Whether the padding shall be absolute. */ paddingAbsolute: boolean; + /** Whether to show the native scrollbars. Has only an effect it the native scrollbars are overlaid. */ showNativeOverlaidScrollbars: boolean; + /** Customizes the automatic update behavior. */ update: { + /** + * The given Event(s) from the elements with the given selector(s) will trigger an update. + * Useful for everything the MutationObserver and ResizeObserver can't detect + * e.g.: and Images `load` event or the `transitionend` / `animationend` events. + */ elementEvents: Array<[elementSelector: string, eventNames: string]> | null; - debounce: [timeout: number, maxWait: number] | number | null; // (if tuple: [timeout: 0, maxWait: 33], if number: [timeout: number, maxWait: false]) debounce for content Changes + /** + * The debounce which is used to detect content changes. + * If a tuple is provided you can customize the `timeout` and the `maxWait` in milliseconds. + * If a single number customizes only the `timeout`. + * + * If the `timeout` is `0`, a debounce still exists. (its executed via `requestAnimationFrame`). + */ + debounce: [timeout: number, maxWait: number] | number | null; + /** + * HTML attributes which will trigger an update if they're changed. + * Basic attributes like `id`, `class`, `style` etc. are always observed and doesn't have to be added explicitly. + */ attributes: string[] | null; + /** + * A function which makes it possible to ignore a content mutation or null if nothing shall be ignored. + * @param mutation The MutationRecord from the MutationObserver. + * @returns A Truthy value if the mutation shall be ignored, a falsy value otherwise. + */ ignoreMutation: ((mutation: MutationRecord) => any) | null; }; + /** Customizes the overflow behavior per axis. */ overflow: { + /** The overflow behavior of the horizontal (x) axis. */ x: OverflowBehavior; + /** The overflow behavior of the vertical (y) axis. */ y: OverflowBehavior; }; + /** Customizes appearance of the scrollbars. */ scrollbars: { + /** + * The scrollbars theme. + * The theme value will be added as `class` to all `scrollbar` elements of the instance. + */ theme: string | null; - visibility: ScrollbarVisibilityBehavior; - autoHide: ScrollbarAutoHideBehavior; + /** The scrollbars visibility behavior. */ + visibility: ScrollbarsVisibilityBehavior; + /** The scrollbars auto hide behavior. */ + autoHide: ScrollbarsAutoHideBehavior; + /** The scrollbars auto hide delay in milliseconds. */ autoHideDelay: number; + /** Whether its possible to drag the handle of a scrollbar to scroll the viewport. */ dragScroll: boolean; + /** Whether its possible to click the track of a scrollbar to scroll the viewport. */ clickScroll: boolean; + /** + * An array of pointer types which shall be supported. + * Common pointer types are: `mouse`, `pen` and `touch`. + * https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerType + */ pointers: string[] | null; }; } diff --git a/packages/overlayscrollbars/src/overlayscrollbars.ts b/packages/overlayscrollbars/src/overlayscrollbars.ts index 4b0bbcd..f918d5a 100644 --- a/packages/overlayscrollbars/src/overlayscrollbars.ts +++ b/packages/overlayscrollbars/src/overlayscrollbars.ts @@ -14,10 +14,11 @@ import { cancelInitialization } from '~/initialization'; import { addInstance, getInstance, removeInstance } from '~/instances'; import { createStructureSetup, createScrollbarsSetup } from '~/setups'; import { getPlugins, addPlugin, optionsValidationPluginName } from '~/plugins'; +import type { Environment } from '~/environment'; import type { XY, TRBL } from '~/support'; import type { Options, ReadonlyOptions } from '~/options'; import type { Plugin, OptionsValidationPluginInstance, PluginInstance } from '~/plugins'; -import type { InitializationTarget, Initialization } from '~/initialization'; +import type { InitializationTarget } from '~/initialization'; import type { DeepPartial, OverflowStyle } from '~/typings'; import type { EventListenerMap, EventListener, InitialEventListeners } from '~/eventListeners'; import type { @@ -28,84 +29,184 @@ import type { // Notes: // Height intrinsic detection use "content: true" init strategy - or open ticket for custom height intrinsic observer +/** + * The primary entry point to OverlayScrollbars. + */ export interface OverlayScrollbarsStatic { + /** + * Returns the current OverlayScrollbars instance if the target already has an instance. + * @param target The initialization target to from which the instance shall be returned. + */ (target: InitializationTarget): OverlayScrollbars | undefined; + /** + * Initialized a new OverlayScrollbars instance to the given target + * or returns the current OverlayScrollbars instance if the target already has an instance. + * @param target The target. + * @param options The options. (Can be just an empty object) + * @param eventListeners Optional event listeners. + */ ( target: InitializationTarget, options: DeepPartial, eventListeners?: InitialEventListeners ): OverlayScrollbars; + /** + * Adds one or multiple plugins. + * @param plugin Either a signle or an array of plugins to add. + */ plugin(plugin: Plugin | Plugin[]): void; + /** + * Checkts whether the passed value is a valid overlayscrollbars instance. + * @param osInstance The value which shall be checked. + */ valid(osInstance: any): osInstance is OverlayScrollbars; + /** + * Returns the overlayscrollbars environment. + */ env(): Environment; } -export interface Environment { - scrollbarsSize: XY; - scrollbarsOverlaid: XY; - scrollbarsHiding: boolean; - rtlScrollBehavior: { n: boolean; i: boolean }; - flexboxGlue: boolean; - cssCustomProperties: boolean; - staticDefaultInitialization: Initialization; - staticDefaultOptions: Options; - - getDefaultInitialization(): Initialization; - setDefaultInitialization(newDefaultInitialization: DeepPartial): void; - getDefaultOptions(): Options; - setDefaultOptions(newDefaultOptions: DeepPartial): void; -} - +/** + * Describes a OverlayScrollbars instances state. + */ export interface State { + /** Describes the current padding in pixel. */ padding: TRBL; + /** Whether the current padding is absolute. */ paddingAbsolute: boolean; + /** The client width (x) & height (y) of the viewport in pixel. */ overflowEdge: XY; + /** The overflow amount in pixel. */ overflowAmount: XY; + /** The css overflow style of the viewport. */ overflowStyle: XY; + /** Whether the viewport has an overflow. */ hasOverflow: XY; + /** Whether the direction is considered rtl. */ directionRTL: boolean; + /** Whether the instance is considered destroyed. */ destroyed: boolean; } +/** + * Describes the elements of a scrollbar. + */ export interface ScrollbarElements { + /** + * The root element of the scrollbar. + * The HTML structure looks like this: + * + * + * + * + * + */ scrollbar: HTMLElement; + /** The track element of the scrollbar. */ track: HTMLElement; + /** The handle element of the scrollbar. */ handle: HTMLElement; } +/** + * Describes the elements of a scrollbar and provides the possibility to clone them. + */ export interface CloneableScrollbarElements extends ScrollbarElements { + /** + * Clones the current scrollbar and returns the cloned elements. + * The returned elements aren't added to the DOM. + */ clone(): ScrollbarElements; } +/** + * Describes the elements of a OverlayScrollbars instance. + */ export interface Elements { + /** The element the instance was applied to. */ target: HTMLElement; + /** The host element. Its the root of all other elements. */ host: HTMLElement; + /** + * The element which is responsible to apply correct paddings. + * Depending on the Initialization it can be the same as the viewport element. + */ padding: HTMLElement; + /** The element which is responsible to do any scrolling. */ viewport: HTMLElement; + /** + * The element which is responsible to hold the content. + * Depending on the Initialization it can be the same as the viewport element. + */ content: HTMLElement; + /** + * The element through which you can get the current `scrollLeft` or `scrollTop` offset. + * Depending on the target element it can be the same as the viewport element. + */ scrollOffsetElement: HTMLElement; + /** + * The element through which you can add `scroll` events. + * Depending on the target element it can be the same as the viewport element. + */ scrollEventElement: HTMLElement | Document; + /** The horizontal scrollbar elements. */ scrollbarHorizontal: CloneableScrollbarElements; + /** The vertical scrollbar elements. */ scrollbarVertical: CloneableScrollbarElements; } +/** + * Describes a OverlayScrollbars instance. + */ export interface OverlayScrollbars { + /** Get the current options of the instance. */ options(): Options; + /** + * Sets the options of the instance. + * If the new options are partially filled, they're deeply merged with the current options. + * @param newOptions The new options. + */ options(newOptions: DeepPartial): Options; + /** + * Adds an event listener to the instance. + * @param name The name of the event. + * @param listener The listener which is invoked on that event. + */ on(name: N, listener: EventListener): () => void; + /** + * Adds multiple event listeners to the instance. + * @param name The name of the event. + * @param listener The listeners which are invoked on that event. + */ on(name: N, listener: EventListener[]): () => void; + /** + * Removes an event listener from the instance. + * @param name The name of the event. + * @param listener The listener which shall be removed. + */ off(name: N, listener: EventListener): void; + /** + * Removes multiple event listeners from the instance. + * @param name The name of the event. + * @param listener The listeners which shall be removed. + */ off(name: N, listener: EventListener[]): void; + /** + * Updates the instance. + * @param force Whether the update should force the cache to be invalidated. + * @returns A boolean which indicates whether the `update` event was triggered through this update. + * The update event is only triggered if something changed because of this update. + */ update(force?: boolean): boolean; - + /** Returns the state of the instance. */ state(): State; - + /** Returns the elements of the instance. */ elements(): Elements; - + /** Destroys the instance. */ destroy(): void; } diff --git a/packages/overlayscrollbars/src/plugins/optionsValidationPlugin/optionsValidationPlugin.ts b/packages/overlayscrollbars/src/plugins/optionsValidationPlugin/optionsValidationPlugin.ts index a8d374e..062421e 100644 --- a/packages/overlayscrollbars/src/plugins/optionsValidationPlugin/optionsValidationPlugin.ts +++ b/packages/overlayscrollbars/src/plugins/optionsValidationPlugin/optionsValidationPlugin.ts @@ -5,8 +5,8 @@ import { import type { Options, OverflowBehavior, - ScrollbarVisibilityBehavior, - ScrollbarAutoHideBehavior, + ScrollbarsVisibilityBehavior, + ScrollbarsAutoHideBehavior, } from '~/options'; import type { OptionsTemplate, @@ -20,9 +20,9 @@ const booleanAllowedValues: OptionsTemplateValue = oTypes.boolean; const arrayNullValues: OptionsTemplateValue | null> = [oTypes.array, oTypes.null]; const overflowAllowedValues: OptionsTemplateValue = 'hidden scroll visible visible-hidden'; -const scrollbarsVisibilityAllowedValues: OptionsTemplateValue = +const scrollbarsVisibilityAllowedValues: OptionsTemplateValue = 'visible hidden auto'; -const scrollbarsAutoHideAllowedValues: OptionsTemplateValue = +const scrollbarsAutoHideAllowedValues: OptionsTemplateValue = 'never scroll leavemove'; const optionsTemplate: OptionsTemplate = { diff --git a/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.ts b/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.ts index c748df0..ab89b08 100644 --- a/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.ts +++ b/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.ts @@ -18,8 +18,8 @@ import type { import type { StructureSetupUpdateHints } from '~/setups/structureSetup/structureSetup.update'; import type { ReadonlyOptions, - ScrollbarVisibilityBehavior, - ScrollbarAutoHideBehavior, + ScrollbarsVisibilityBehavior, + ScrollbarsAutoHideBehavior, } from '~/options'; import type { Setup, StructureSetupState, StructureSetupStaticState } from '~/setups'; import type { InitializationTarget } from '~/initialization'; @@ -164,9 +164,9 @@ export const createScrollbarsSetup = ( const { _overflowAmount, _overflowStyle, _directionIsRTL } = currStructureSetupState; const [theme, themeChanged] = checkOption('scrollbars.theme'); const [visibility, visibilityChanged] = - checkOption('scrollbars.visibility'); + checkOption('scrollbars.visibility'); const [autoHide, autoHideChanged] = - checkOption('scrollbars.autoHide'); + checkOption('scrollbars.autoHide'); const [autoHideDelay] = checkOption('scrollbars.autoHideDelay'); const [dragScroll, dragScrollChanged] = checkOption('scrollbars.dragScroll'); const [clickScroll, clickScrollChanged] = checkOption('scrollbars.clickScroll'); diff --git a/packages/overlayscrollbars/src/styles/structure.scss b/packages/overlayscrollbars/src/styles/structure.scss index 5f51ffd..d3d29da 100644 --- a/packages/overlayscrollbars/src/styles/structure.scss +++ b/packages/overlayscrollbars/src/styles/structure.scss @@ -1,3 +1,7 @@ +/** + * environment setup + */ + .os-environment { --os-custom-prop: -1; position: fixed; @@ -49,6 +53,10 @@ } } +/** + * hide native scrollbars + */ + .os-environment, .os-viewport { -ms-overflow-style: scrollbar !important; @@ -77,6 +85,10 @@ html.os-viewport-scrollbar-hidden::-webkit-scrollbar-corner, background: transparent !important; } +/** + * applied to body + */ + html.os-viewport-scrollbar-hidden, html.os-viewport-scrollbar-hidden > body[data-overlayscrollbars] { box-sizing: border-box; @@ -85,11 +97,14 @@ html.os-viewport-scrollbar-hidden > body[data-overlayscrollbars] { height: 100%; } +/** + * structure setup + */ + [data-overlayscrollbars~='host'], .os-padding { position: relative; } - [data-overlayscrollbars~='host'], .os-padding { display: flex; @@ -97,19 +112,6 @@ html.os-viewport-scrollbar-hidden > body[data-overlayscrollbars] { flex-wrap: nowrap !important; } -[data-overlayscrollbars~='grid'], -[data-overlayscrollbars~='grid'] .os-padding { - display: grid; - grid-template: 1fr / 1fr; -} - -[data-overlayscrollbars~='grid'] > .os-padding, -[data-overlayscrollbars~='grid'] > .os-viewport, -[data-overlayscrollbars~='grid'] > .os-padding > .os-viewport { - height: auto !important; - width: auto !important; -} - .os-padding, .os-viewport { box-sizing: inherit; @@ -171,3 +173,19 @@ html.os-viewport-scrollbar-hidden > body[data-overlayscrollbars] { .os-content { box-sizing: inherit; } + +/** + * optional & experimental grid mode + */ + +[data-overlayscrollbars-grid], +[data-overlayscrollbars-grid] .os-padding { + display: grid; + grid-template: 1fr / 1fr; +} +[data-overlayscrollbars-grid] > .os-padding, +[data-overlayscrollbars-grid] > .os-viewport, +[data-overlayscrollbars-grid] > .os-padding > .os-viewport { + height: auto !important; + width: auto !important; +} diff --git a/packages/overlayscrollbars/src/support/dom/style.ts b/packages/overlayscrollbars/src/support/dom/style.ts index 3e19aa2..3746b16 100644 --- a/packages/overlayscrollbars/src/support/dom/style.ts +++ b/packages/overlayscrollbars/src/support/dom/style.ts @@ -112,9 +112,9 @@ export const topRightBottomLeft = ( const left = `${finalPrefix}left${finalSuffix}`; const result = style(elm, [top, right, bottom, left]); return { - t: parseToZeroOrNumber(result[top]), - r: parseToZeroOrNumber(result[right]), - b: parseToZeroOrNumber(result[bottom]), - l: parseToZeroOrNumber(result[left]), + t: parseToZeroOrNumber(result[top], true), + r: parseToZeroOrNumber(result[right], true), + b: parseToZeroOrNumber(result[bottom], true), + l: parseToZeroOrNumber(result[left], true), }; };