mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-22 16:50:36 +03:00
start with events
This commit is contained in:
+107
-15
@@ -108,14 +108,22 @@ const push = (array, items, arrayIsSingleItem) => {
|
|||||||
return array;
|
return array;
|
||||||
};
|
};
|
||||||
const from = arr => {
|
const from = arr => {
|
||||||
if (Array.from) {
|
if (Array.from && arr) {
|
||||||
return Array.from(arr);
|
return Array.from(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = [];
|
const result = [];
|
||||||
each(arr, elm => {
|
|
||||||
push(result, elm);
|
if (arr instanceof Set) {
|
||||||
});
|
arr.forEach(value => {
|
||||||
|
push(result, value);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
each(arr, elm => {
|
||||||
|
push(result, elm);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
const isEmptyArray = array => !!array && array.length === 0;
|
const isEmptyArray = array => !!array && array.length === 0;
|
||||||
@@ -933,8 +941,8 @@ const createUniqueViewportArrangeElement = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const staticCreationFromStrategy = (target, initializationValue, strategy, elementClass) => {
|
const staticCreationFromStrategy = (target, initializationValue, strategy, elementClass) => {
|
||||||
const result = initializationValue ? initializationValue : isFunction(strategy) ? strategy(target) : strategy;
|
const result = initializationValue || (isFunction(strategy) ? strategy(target) : strategy);
|
||||||
return result ? result : createDiv(elementClass);
|
return result || createDiv(elementClass);
|
||||||
};
|
};
|
||||||
|
|
||||||
const dynamicCreationFromStrategy = (target, initializationValue, strategy, elementClass, defaultValue) => {
|
const dynamicCreationFromStrategy = (target, initializationValue, strategy, elementClass, defaultValue) => {
|
||||||
@@ -2219,7 +2227,7 @@ const lifecycleCommunicationFallback = {
|
|||||||
paddingLeft: 0
|
paddingLeft: 0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const createLifecycleHub = (options, structureSetup, scrollbarsSetup) => {
|
const createLifecycleHub = (options, triggerEvent, structureSetup, scrollbarsSetup) => {
|
||||||
let lifecycleCommunication = lifecycleCommunicationFallback;
|
let lifecycleCommunication = lifecycleCommunicationFallback;
|
||||||
const {
|
const {
|
||||||
_viewport
|
_viewport
|
||||||
@@ -2295,9 +2303,17 @@ const createLifecycleHub = (options, structureSetup, scrollbarsSetup) => {
|
|||||||
scrollTop(_viewport, scrollOffsetY);
|
scrollTop(_viewport, scrollOffsetY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.callbacks.onUpdated) {
|
triggerEvent('updated', {
|
||||||
options.callbacks.onUpdated();
|
updateHints: {
|
||||||
}
|
sizeChanged: _sizeChanged,
|
||||||
|
contentMutation: _contentMutation,
|
||||||
|
hostMutation: _hostMutation,
|
||||||
|
directionChanged: finalDirectionIsRTL[1],
|
||||||
|
heightIntrinsicChanged: finalHeightIntrinsic[1]
|
||||||
|
},
|
||||||
|
changedOptions: changedOptions || {},
|
||||||
|
force: !!force
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -2385,21 +2401,89 @@ const scrollbarsAutoHideAllowedValues = 'never scroll leavemove';
|
|||||||
});
|
});
|
||||||
const optionsValidationPluginName = '__osOptionsValidationPlugin';
|
const optionsValidationPluginName = '__osOptionsValidationPlugin';
|
||||||
|
|
||||||
|
const targets = new Set();
|
||||||
|
const targetInstanceMap = new WeakMap();
|
||||||
|
const addInstance = (target, osInstance) => {
|
||||||
|
targetInstanceMap.set(target, osInstance);
|
||||||
|
targets.add(target);
|
||||||
|
};
|
||||||
|
const removeInstance = target => {
|
||||||
|
targetInstanceMap.delete(target);
|
||||||
|
targets.delete(target);
|
||||||
|
};
|
||||||
|
const getInstance = target => targetInstanceMap.get(target);
|
||||||
|
|
||||||
|
const manageListener = (callback, listener) => {
|
||||||
|
each(isArray(listener) ? listener : [listener], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
const createEventHub = () => {
|
||||||
|
const events = new Map();
|
||||||
|
|
||||||
|
const removeEvent = (name, listener) => {
|
||||||
|
if (name) {
|
||||||
|
const eventSet = events.get(name);
|
||||||
|
manageListener(currListener => {
|
||||||
|
if (eventSet) {
|
||||||
|
eventSet[currListener ? 'delete' : 'clear'](currListener);
|
||||||
|
}
|
||||||
|
}, listener);
|
||||||
|
} else {
|
||||||
|
events.forEach(eventSet => {
|
||||||
|
eventSet.clear();
|
||||||
|
});
|
||||||
|
events.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addEvent = (name, listener) => {
|
||||||
|
const eventSet = events.get(name) || new Set();
|
||||||
|
events.set(name, eventSet);
|
||||||
|
manageListener(currListener => {
|
||||||
|
eventSet.add(currListener);
|
||||||
|
}, listener);
|
||||||
|
return removeEvent.bind(0, name, listener);
|
||||||
|
};
|
||||||
|
|
||||||
|
const triggerEvent = (name, args) => {
|
||||||
|
const eventSet = events.get(name);
|
||||||
|
each(from(eventSet), event => {
|
||||||
|
event(args);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return [addEvent, removeEvent, triggerEvent];
|
||||||
|
};
|
||||||
|
|
||||||
const OverlayScrollbars = (target, options) => {
|
const OverlayScrollbars = (target, options) => {
|
||||||
|
const instanceTarget = isHTMLElement(target) ? target : target.target;
|
||||||
|
const potentialInstance = getInstance(instanceTarget);
|
||||||
|
|
||||||
|
if (potentialInstance) {
|
||||||
|
return potentialInstance;
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
_getDefaultOptions
|
_getDefaultOptions
|
||||||
} = getEnvironment();
|
} = getEnvironment();
|
||||||
const plugins = getPlugins();
|
const plugins = getPlugins();
|
||||||
const optionsValidationPlugin = plugins[optionsValidationPluginName];
|
const optionsValidationPlugin = plugins[optionsValidationPluginName];
|
||||||
const validateOptions = optionsValidationPlugin && optionsValidationPlugin._;
|
|
||||||
const currentOptions = assignDeep({}, _getDefaultOptions(), validateOptions ? validateOptions(options || {}, true) : options);
|
const validateOptions = newOptions => {
|
||||||
|
const opts = newOptions || {};
|
||||||
|
const validate = optionsValidationPlugin && optionsValidationPlugin._;
|
||||||
|
return validate ? validate(opts, true) : opts;
|
||||||
|
};
|
||||||
|
|
||||||
|
const [addEvent, removeEvent, triggerEvent] = createEventHub();
|
||||||
|
const currentOptions = assignDeep({}, _getDefaultOptions(), validateOptions(options));
|
||||||
const structureSetup = createStructureSetup(target);
|
const structureSetup = createStructureSetup(target);
|
||||||
const scrollbarsSetup = createScrollbarsSetup(target, structureSetup);
|
const scrollbarsSetup = createScrollbarsSetup(target, structureSetup);
|
||||||
const lifecycleHub = createLifecycleHub(currentOptions, structureSetup, scrollbarsSetup);
|
const lifecycleHub = createLifecycleHub(currentOptions, triggerEvent, structureSetup, scrollbarsSetup);
|
||||||
const instance = {
|
const instance = {
|
||||||
options(newOptions) {
|
options(newOptions) {
|
||||||
if (newOptions) {
|
if (newOptions) {
|
||||||
const changedOptions = getOptionsDiff(currentOptions, validateOptions ? validateOptions(newOptions, true) : newOptions);
|
const changedOptions = getOptionsDiff(currentOptions, validateOptions(newOptions));
|
||||||
|
|
||||||
if (!isEmptyObject(changedOptions)) {
|
if (!isEmptyObject(changedOptions)) {
|
||||||
assignDeep(currentOptions, changedOptions);
|
assignDeep(currentOptions, changedOptions);
|
||||||
@@ -2411,13 +2495,20 @@ const OverlayScrollbars = (target, options) => {
|
|||||||
return currentOptions;
|
return currentOptions;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
on: addEvent,
|
||||||
|
off: removeEvent,
|
||||||
state: () => lifecycleHub._state(),
|
state: () => lifecycleHub._state(),
|
||||||
|
|
||||||
update(force) {
|
update(force) {
|
||||||
lifecycleHub._update({}, force);
|
lifecycleHub._update({}, force);
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: () => lifecycleHub._destroy()
|
destroy: () => {
|
||||||
|
lifecycleHub._destroy();
|
||||||
|
|
||||||
|
removeInstance(instanceTarget);
|
||||||
|
removeEvent();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
each(keys(plugins), pluginName => {
|
each(keys(plugins), pluginName => {
|
||||||
const pluginInstance = plugins[pluginName];
|
const pluginInstance = plugins[pluginName];
|
||||||
@@ -2427,6 +2518,7 @@ const OverlayScrollbars = (target, options) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
instance.update(true);
|
instance.update(true);
|
||||||
|
addInstance(instanceTarget, instance);
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
OverlayScrollbars.extend = addPlugin;
|
OverlayScrollbars.extend = addPlugin;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+111
-15
@@ -121,14 +121,22 @@
|
|||||||
return array;
|
return array;
|
||||||
};
|
};
|
||||||
var from = function from(arr) {
|
var from = function from(arr) {
|
||||||
if (Array.from) {
|
if (Array.from && arr) {
|
||||||
return Array.from(arr);
|
return Array.from(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = [];
|
var result = [];
|
||||||
each(arr, function (elm) {
|
|
||||||
push(result, elm);
|
if (arr instanceof Set) {
|
||||||
});
|
arr.forEach(function (value) {
|
||||||
|
push(result, value);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
each(arr, function (elm) {
|
||||||
|
push(result, elm);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
var isEmptyArray = function isEmptyArray(array) {
|
var isEmptyArray = function isEmptyArray(array) {
|
||||||
@@ -1005,8 +1013,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
var staticCreationFromStrategy = function staticCreationFromStrategy(target, initializationValue, strategy, elementClass) {
|
var staticCreationFromStrategy = function staticCreationFromStrategy(target, initializationValue, strategy, elementClass) {
|
||||||
var result = initializationValue ? initializationValue : isFunction(strategy) ? strategy(target) : strategy;
|
var result = initializationValue || (isFunction(strategy) ? strategy(target) : strategy);
|
||||||
return result ? result : createDiv(elementClass);
|
return result || createDiv(elementClass);
|
||||||
};
|
};
|
||||||
|
|
||||||
var dynamicCreationFromStrategy = function dynamicCreationFromStrategy(target, initializationValue, strategy, elementClass, defaultValue) {
|
var dynamicCreationFromStrategy = function dynamicCreationFromStrategy(target, initializationValue, strategy, elementClass, defaultValue) {
|
||||||
@@ -2311,7 +2319,7 @@
|
|||||||
paddingLeft: 0
|
paddingLeft: 0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var createLifecycleHub = function createLifecycleHub(options, structureSetup, scrollbarsSetup) {
|
var createLifecycleHub = function createLifecycleHub(options, triggerEvent, structureSetup, scrollbarsSetup) {
|
||||||
var lifecycleCommunication = lifecycleCommunicationFallback;
|
var lifecycleCommunication = lifecycleCommunicationFallback;
|
||||||
var _viewport = structureSetup._targetObj._viewport;
|
var _viewport = structureSetup._targetObj._viewport;
|
||||||
|
|
||||||
@@ -2392,9 +2400,17 @@
|
|||||||
scrollTop(_viewport, scrollOffsetY);
|
scrollTop(_viewport, scrollOffsetY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.callbacks.onUpdated) {
|
triggerEvent('updated', {
|
||||||
options.callbacks.onUpdated();
|
updateHints: {
|
||||||
}
|
sizeChanged: _sizeChanged,
|
||||||
|
contentMutation: _contentMutation,
|
||||||
|
hostMutation: _hostMutation,
|
||||||
|
directionChanged: finalDirectionIsRTL[1],
|
||||||
|
heightIntrinsicChanged: finalHeightIntrinsic[1]
|
||||||
|
},
|
||||||
|
changedOptions: changedOptions || {},
|
||||||
|
force: !!force
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var _lifecycleHubOservers = lifecycleHubOservers(instance, updateLifecycles),
|
var _lifecycleHubOservers = lifecycleHubOservers(instance, updateLifecycles),
|
||||||
@@ -2487,21 +2503,95 @@
|
|||||||
});
|
});
|
||||||
var optionsValidationPluginName = '__osOptionsValidationPlugin';
|
var optionsValidationPluginName = '__osOptionsValidationPlugin';
|
||||||
|
|
||||||
|
var targets = new Set();
|
||||||
|
var targetInstanceMap = new WeakMap();
|
||||||
|
var addInstance = function addInstance(target, osInstance) {
|
||||||
|
targetInstanceMap.set(target, osInstance);
|
||||||
|
targets.add(target);
|
||||||
|
};
|
||||||
|
var removeInstance = function removeInstance(target) {
|
||||||
|
targetInstanceMap.delete(target);
|
||||||
|
targets.delete(target);
|
||||||
|
};
|
||||||
|
var getInstance = function getInstance(target) {
|
||||||
|
return targetInstanceMap.get(target);
|
||||||
|
};
|
||||||
|
|
||||||
|
var manageListener = function manageListener(callback, listener) {
|
||||||
|
each(isArray(listener) ? listener : [listener], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
var createEventHub = function createEventHub() {
|
||||||
|
var events = new Map();
|
||||||
|
|
||||||
|
var removeEvent = function removeEvent(name, listener) {
|
||||||
|
if (name) {
|
||||||
|
var eventSet = events.get(name);
|
||||||
|
manageListener(function (currListener) {
|
||||||
|
if (eventSet) {
|
||||||
|
eventSet[currListener ? 'delete' : 'clear'](currListener);
|
||||||
|
}
|
||||||
|
}, listener);
|
||||||
|
} else {
|
||||||
|
events.forEach(function (eventSet) {
|
||||||
|
eventSet.clear();
|
||||||
|
});
|
||||||
|
events.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var addEvent = function addEvent(name, listener) {
|
||||||
|
var eventSet = events.get(name) || new Set();
|
||||||
|
events.set(name, eventSet);
|
||||||
|
manageListener(function (currListener) {
|
||||||
|
eventSet.add(currListener);
|
||||||
|
}, listener);
|
||||||
|
return removeEvent.bind(0, name, listener);
|
||||||
|
};
|
||||||
|
|
||||||
|
var triggerEvent = function triggerEvent(name, args) {
|
||||||
|
var eventSet = events.get(name);
|
||||||
|
each(from(eventSet), function (event) {
|
||||||
|
event(args);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return [addEvent, removeEvent, triggerEvent];
|
||||||
|
};
|
||||||
|
|
||||||
var OverlayScrollbars = function OverlayScrollbars(target, options) {
|
var OverlayScrollbars = function OverlayScrollbars(target, options) {
|
||||||
|
var instanceTarget = isHTMLElement(target) ? target : target.target;
|
||||||
|
var potentialInstance = getInstance(instanceTarget);
|
||||||
|
|
||||||
|
if (potentialInstance) {
|
||||||
|
return potentialInstance;
|
||||||
|
}
|
||||||
|
|
||||||
var _getEnvironment = getEnvironment(),
|
var _getEnvironment = getEnvironment(),
|
||||||
_getDefaultOptions = _getEnvironment._getDefaultOptions;
|
_getDefaultOptions = _getEnvironment._getDefaultOptions;
|
||||||
|
|
||||||
var plugins = getPlugins();
|
var plugins = getPlugins();
|
||||||
var optionsValidationPlugin = plugins[optionsValidationPluginName];
|
var optionsValidationPlugin = plugins[optionsValidationPluginName];
|
||||||
var validateOptions = optionsValidationPlugin && optionsValidationPlugin._;
|
|
||||||
var currentOptions = assignDeep({}, _getDefaultOptions(), validateOptions ? validateOptions(options || {}, true) : options);
|
var validateOptions = function validateOptions(newOptions) {
|
||||||
|
var opts = newOptions || {};
|
||||||
|
var validate = optionsValidationPlugin && optionsValidationPlugin._;
|
||||||
|
return validate ? validate(opts, true) : opts;
|
||||||
|
};
|
||||||
|
|
||||||
|
var _createEventHub = createEventHub(),
|
||||||
|
addEvent = _createEventHub[0],
|
||||||
|
removeEvent = _createEventHub[1],
|
||||||
|
triggerEvent = _createEventHub[2];
|
||||||
|
|
||||||
|
var currentOptions = assignDeep({}, _getDefaultOptions(), validateOptions(options));
|
||||||
var structureSetup = createStructureSetup(target);
|
var structureSetup = createStructureSetup(target);
|
||||||
var scrollbarsSetup = createScrollbarsSetup(target, structureSetup);
|
var scrollbarsSetup = createScrollbarsSetup(target, structureSetup);
|
||||||
var lifecycleHub = createLifecycleHub(currentOptions, structureSetup, scrollbarsSetup);
|
var lifecycleHub = createLifecycleHub(currentOptions, triggerEvent, structureSetup, scrollbarsSetup);
|
||||||
var instance = {
|
var instance = {
|
||||||
options: function options(newOptions) {
|
options: function options(newOptions) {
|
||||||
if (newOptions) {
|
if (newOptions) {
|
||||||
var changedOptions = getOptionsDiff(currentOptions, validateOptions ? validateOptions(newOptions, true) : newOptions);
|
var changedOptions = getOptionsDiff(currentOptions, validateOptions(newOptions));
|
||||||
|
|
||||||
if (!isEmptyObject(changedOptions)) {
|
if (!isEmptyObject(changedOptions)) {
|
||||||
assignDeep(currentOptions, changedOptions);
|
assignDeep(currentOptions, changedOptions);
|
||||||
@@ -2512,6 +2602,8 @@
|
|||||||
|
|
||||||
return currentOptions;
|
return currentOptions;
|
||||||
},
|
},
|
||||||
|
on: addEvent,
|
||||||
|
off: removeEvent,
|
||||||
state: function state() {
|
state: function state() {
|
||||||
return lifecycleHub._state();
|
return lifecycleHub._state();
|
||||||
},
|
},
|
||||||
@@ -2519,7 +2611,10 @@
|
|||||||
lifecycleHub._update({}, force);
|
lifecycleHub._update({}, force);
|
||||||
},
|
},
|
||||||
destroy: function destroy() {
|
destroy: function destroy() {
|
||||||
return lifecycleHub._destroy();
|
lifecycleHub._destroy();
|
||||||
|
|
||||||
|
removeInstance(instanceTarget);
|
||||||
|
removeEvent();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
each(keys(plugins), function (pluginName) {
|
each(keys(plugins), function (pluginName) {
|
||||||
@@ -2530,6 +2625,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
instance.update(true);
|
instance.update(true);
|
||||||
|
addInstance(instanceTarget, instance);
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
OverlayScrollbars.extend = addPlugin;
|
OverlayScrollbars.extend = addPlugin;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,81 @@
|
|||||||
|
import { OSOptions } from 'options';
|
||||||
|
import { each, from, isArray } from 'support';
|
||||||
|
import { PartialOptions } from 'typings';
|
||||||
|
|
||||||
|
export interface onUpdatedEventArgs {
|
||||||
|
updateHints: {
|
||||||
|
sizeChanged: boolean;
|
||||||
|
hostMutation: boolean;
|
||||||
|
contentMutation: boolean;
|
||||||
|
directionChanged: boolean;
|
||||||
|
heightIntrinsicChanged: boolean;
|
||||||
|
};
|
||||||
|
changedOptions: PartialOptions<OSOptions>;
|
||||||
|
force: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EventArgsMap {
|
||||||
|
updated: onUpdatedEventArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OSEventListener<N extends keyof EventArgsMap> = (args: EventArgsMap[N]) => void;
|
||||||
|
|
||||||
|
export type AddEvent = <N extends keyof EventArgsMap>(
|
||||||
|
name: N,
|
||||||
|
listener: OSEventListener<N> | OSEventListener<N>[]
|
||||||
|
) => () => void;
|
||||||
|
|
||||||
|
export type RemoveEvent = <N extends keyof EventArgsMap>(
|
||||||
|
name?: N,
|
||||||
|
listener?: OSEventListener<N> | OSEventListener<N>[]
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
export type TriggerEvent = <N extends keyof EventArgsMap>(name: N, args: EventArgsMap[N]) => void;
|
||||||
|
|
||||||
|
export type EventHub = [AddEvent, RemoveEvent, TriggerEvent];
|
||||||
|
|
||||||
|
const manageListener = <N extends keyof EventArgsMap>(
|
||||||
|
callback: (listener?: OSEventListener<any>) => void,
|
||||||
|
listener?: OSEventListener<N> | OSEventListener<N>[]
|
||||||
|
) => {
|
||||||
|
each(isArray(listener) ? listener : [listener], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createEventHub = (): EventHub => {
|
||||||
|
const events = new Map<string, Set<OSEventListener<any>>>();
|
||||||
|
const removeEvent: RemoveEvent = (name?, listener?) => {
|
||||||
|
if (name) {
|
||||||
|
const eventSet = events.get(name);
|
||||||
|
|
||||||
|
manageListener((currListener) => {
|
||||||
|
if (eventSet) {
|
||||||
|
eventSet[currListener ? 'delete' : 'clear'](currListener!);
|
||||||
|
}
|
||||||
|
}, listener);
|
||||||
|
} else {
|
||||||
|
events.forEach((eventSet) => {
|
||||||
|
eventSet.clear();
|
||||||
|
});
|
||||||
|
events.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const addEvent: AddEvent = (name, listener) => {
|
||||||
|
const eventSet = events.get(name) || new Set();
|
||||||
|
events.set(name, eventSet);
|
||||||
|
|
||||||
|
manageListener((currListener) => {
|
||||||
|
eventSet.add(currListener!);
|
||||||
|
}, listener);
|
||||||
|
|
||||||
|
return removeEvent.bind(0, name, listener as any);
|
||||||
|
};
|
||||||
|
const triggerEvent: TriggerEvent = (name, args) => {
|
||||||
|
const eventSet = events.get(name);
|
||||||
|
|
||||||
|
each(from(eventSet), (event) => {
|
||||||
|
event(args);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return [addEvent, removeEvent, triggerEvent];
|
||||||
|
};
|
||||||
@@ -26,11 +26,12 @@ export const removeInstance = (target: Element): void => {
|
|||||||
* Gets the OverlayScrollbars from the given element or undefined if it doesn't have one.
|
* Gets the OverlayScrollbars from the given element or undefined if it doesn't have one.
|
||||||
* @param target The element of which its OverlayScrollbars instance shall be get.
|
* @param target The element of which its OverlayScrollbars instance shall be get.
|
||||||
*/
|
*/
|
||||||
export const getInstance = (target: Element): OverlayScrollbars | undefined => targetInstanceMap.get(target);
|
export const getInstance = (target: Element): OverlayScrollbars | undefined =>
|
||||||
|
targetInstanceMap.get(target);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a Map which represents all active OverayScrollbars instances.
|
* Gets a Map which represents all active OverayScrollbars instances.
|
||||||
* The Key is the ekement and the value is the instance.
|
* The Key is the element and the value is the instance.
|
||||||
*/
|
*/
|
||||||
export const allInstances = (): ReadonlyMap<Element, OverlayScrollbars> => {
|
export const allInstances = (): ReadonlyMap<Element, OverlayScrollbars> => {
|
||||||
const validTargetInstanceMap: Map<Element, OverlayScrollbars> = new Map();
|
const validTargetInstanceMap: Map<Element, OverlayScrollbars> = new Map();
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { createPaddingLifecycle } from 'lifecycles/paddingLifecycle';
|
|||||||
import { createOverflowLifecycle } from 'lifecycles/overflowLifecycle';
|
import { createOverflowLifecycle } from 'lifecycles/overflowLifecycle';
|
||||||
import { StyleObject, PartialOptions } from 'typings';
|
import { StyleObject, PartialOptions } from 'typings';
|
||||||
import { ScrollbarsSetup } from 'setups/scrollbarsSetup';
|
import { ScrollbarsSetup } from 'setups/scrollbarsSetup';
|
||||||
|
import { TriggerEvent } from '../events';
|
||||||
|
|
||||||
export type LifecycleCheckOption = <T>(path: string) => LifecycleOptionInfo<T>;
|
export type LifecycleCheckOption = <T>(path: string) => LifecycleOptionInfo<T>;
|
||||||
|
|
||||||
@@ -108,6 +109,7 @@ const lifecycleCommunicationFallback: LifecycleCommunication = {
|
|||||||
|
|
||||||
export const createLifecycleHub = (
|
export const createLifecycleHub = (
|
||||||
options: OSOptions,
|
options: OSOptions,
|
||||||
|
triggerEvent: TriggerEvent,
|
||||||
structureSetup: StructureSetup,
|
structureSetup: StructureSetup,
|
||||||
scrollbarsSetup: ScrollbarsSetup
|
scrollbarsSetup: ScrollbarsSetup
|
||||||
): LifecycleHubInstance => {
|
): LifecycleHubInstance => {
|
||||||
@@ -208,9 +210,17 @@ export const createLifecycleHub = (
|
|||||||
scrollTop(_viewport, scrollOffsetY);
|
scrollTop(_viewport, scrollOffsetY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.callbacks.onUpdated) {
|
triggerEvent('updated', {
|
||||||
options.callbacks.onUpdated();
|
updateHints: {
|
||||||
}
|
sizeChanged: _sizeChanged,
|
||||||
|
contentMutation: _contentMutation,
|
||||||
|
hostMutation: _hostMutation,
|
||||||
|
directionChanged: finalDirectionIsRTL[1],
|
||||||
|
heightIntrinsicChanged: finalHeightIntrinsic[1],
|
||||||
|
},
|
||||||
|
changedOptions: changedOptions || {},
|
||||||
|
force: !!force,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
const {
|
const {
|
||||||
_sizeObserver,
|
_sizeObserver,
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import {
|
|||||||
OSPlugin,
|
OSPlugin,
|
||||||
OptionsValidationPluginInstance,
|
OptionsValidationPluginInstance,
|
||||||
} from 'plugins';
|
} from 'plugins';
|
||||||
import { addInstance, getInstance } from 'instances';
|
import { addInstance, getInstance, removeInstance } from 'instances';
|
||||||
|
import { createEventHub, AddEvent, RemoveEvent } from './events';
|
||||||
|
|
||||||
export interface OverlayScrollbarsStatic {
|
export interface OverlayScrollbarsStatic {
|
||||||
(
|
(
|
||||||
@@ -32,13 +33,17 @@ export interface OverlayScrollbars {
|
|||||||
destroy(): void;
|
destroy(): void;
|
||||||
|
|
||||||
state(): any;
|
state(): any;
|
||||||
|
|
||||||
|
on: AddEvent;
|
||||||
|
off: RemoveEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
||||||
target: OSTarget | OSInitializationObject,
|
target: OSTarget | OSInitializationObject,
|
||||||
options?: PartialOptions<OSOptions>
|
options?: PartialOptions<OSOptions>
|
||||||
): OverlayScrollbars => {
|
): OverlayScrollbars => {
|
||||||
const potentialInstance = getInstance(isHTMLElement(target) ? target : target.target);
|
const instanceTarget = isHTMLElement(target) ? target : target.target;
|
||||||
|
const potentialInstance = getInstance(instanceTarget);
|
||||||
if (potentialInstance) {
|
if (potentialInstance) {
|
||||||
return potentialInstance;
|
return potentialInstance;
|
||||||
}
|
}
|
||||||
@@ -53,10 +58,16 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
|||||||
const validate = optionsValidationPlugin && optionsValidationPlugin._;
|
const validate = optionsValidationPlugin && optionsValidationPlugin._;
|
||||||
return validate ? validate(opts, true) : opts;
|
return validate ? validate(opts, true) : opts;
|
||||||
};
|
};
|
||||||
|
const [addEvent, removeEvent, triggerEvent] = createEventHub();
|
||||||
const currentOptions: OSOptions = assignDeep({}, _getDefaultOptions(), validateOptions(options));
|
const currentOptions: OSOptions = assignDeep({}, _getDefaultOptions(), validateOptions(options));
|
||||||
const structureSetup: StructureSetup = createStructureSetup(target);
|
const structureSetup: StructureSetup = createStructureSetup(target);
|
||||||
const scrollbarsSetup: ScrollbarsSetup = createScrollbarsSetup(target, structureSetup);
|
const scrollbarsSetup: ScrollbarsSetup = createScrollbarsSetup(target, structureSetup);
|
||||||
const lifecycleHub = createLifecycleHub(currentOptions, structureSetup, scrollbarsSetup);
|
const lifecycleHub = createLifecycleHub(
|
||||||
|
currentOptions,
|
||||||
|
triggerEvent,
|
||||||
|
structureSetup,
|
||||||
|
scrollbarsSetup
|
||||||
|
);
|
||||||
|
|
||||||
const instance: OverlayScrollbars = {
|
const instance: OverlayScrollbars = {
|
||||||
options(newOptions?: PartialOptions<OSOptions>) {
|
options(newOptions?: PartialOptions<OSOptions>) {
|
||||||
@@ -70,11 +81,17 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
|||||||
}
|
}
|
||||||
return currentOptions;
|
return currentOptions;
|
||||||
},
|
},
|
||||||
|
on: addEvent,
|
||||||
|
off: removeEvent,
|
||||||
state: () => lifecycleHub._state(),
|
state: () => lifecycleHub._state(),
|
||||||
update(force?: boolean) {
|
update(force?: boolean) {
|
||||||
lifecycleHub._update({}, force);
|
lifecycleHub._update({}, force);
|
||||||
},
|
},
|
||||||
destroy: () => lifecycleHub._destroy(),
|
destroy: () => {
|
||||||
|
lifecycleHub._destroy();
|
||||||
|
removeInstance(instanceTarget);
|
||||||
|
removeEvent();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
each(keys(plugins), (pluginName) => {
|
each(keys(plugins), (pluginName) => {
|
||||||
@@ -86,7 +103,7 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
|||||||
|
|
||||||
instance.update(true);
|
instance.update(true);
|
||||||
|
|
||||||
addInstance(structureSetup._targetObj._target, instance);
|
addInstance(instanceTarget, instance);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -75,15 +75,21 @@ export const push = <T>(array: T[], items: T | ArrayLike<T>, arrayIsSingleItem?:
|
|||||||
* Creates a shallow-copied Array instance from an array-like or iterable object.
|
* Creates a shallow-copied Array instance from an array-like or iterable object.
|
||||||
* @param arr The object from which the array instance shall be created.
|
* @param arr The object from which the array instance shall be created.
|
||||||
*/
|
*/
|
||||||
export const from = <T = any>(arr: ArrayLike<T> | Set<T>) => {
|
export const from = <T = any>(arr?: ArrayLike<T> | Set<T>) => {
|
||||||
if (Array.from) {
|
if (Array.from && arr) {
|
||||||
return Array.from(arr);
|
return Array.from(arr);
|
||||||
}
|
}
|
||||||
const result: T[] = [];
|
const result: T[] = [];
|
||||||
|
|
||||||
each(arr, (elm) => {
|
if (arr instanceof Set) {
|
||||||
push(result, elm);
|
arr.forEach((value) => {
|
||||||
});
|
push(result, value);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
each(arr, (elm) => {
|
||||||
|
push(result, elm);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -278,6 +278,15 @@ describe('array utilities', () => {
|
|||||||
expect(fromChildNodes).toEqual(Array.from(document.body.childNodes));
|
expect(fromChildNodes).toEqual(Array.from(document.body.childNodes));
|
||||||
document.body.innerHTML = '';
|
document.body.innerHTML = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('fallback with Set', () => {
|
||||||
|
const arrFrom = Array.from;
|
||||||
|
// @ts-ignore
|
||||||
|
Array.from = undefined;
|
||||||
|
const fromResult = from(new Set([1, 2, 3]));
|
||||||
|
Array.from = arrFrom;
|
||||||
|
expect(fromResult).toEqual([1, 2, 3]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('runEach', () => {
|
describe('runEach', () => {
|
||||||
|
|||||||
+20
-1
@@ -85,10 +85,27 @@ interface OSOptions {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
type OSPluginInstance = Record<string, unknown> | ((staticObj: OverlayScrollbarsStatic, instanceObj: OverlayScrollbars) => void);
|
type OSPluginInstance = Record<string, unknown> | ((staticObj: OverlayScrollbarsStatic, instanceObj: OverlayScrollbars) => void);
|
||||||
type OSPlugin<T extends OSPluginInstance = OSPluginInstance> = [
|
type OSPlugin<T extends OSPluginInstance> = [
|
||||||
string,
|
string,
|
||||||
T
|
T
|
||||||
];
|
];
|
||||||
|
interface onUpdatedEventArgs {
|
||||||
|
updateHints: {
|
||||||
|
sizeChanged: boolean;
|
||||||
|
hostMutation: boolean;
|
||||||
|
contentMutation: boolean;
|
||||||
|
directionChanged: boolean;
|
||||||
|
heightIntrinsicChanged: boolean;
|
||||||
|
};
|
||||||
|
changedOptions: PartialOptions<OSOptions>;
|
||||||
|
force: boolean;
|
||||||
|
}
|
||||||
|
interface EventArgsMap {
|
||||||
|
updated: onUpdatedEventArgs;
|
||||||
|
}
|
||||||
|
type OSEventListener<N extends keyof EventArgsMap> = (args: EventArgsMap[N]) => void;
|
||||||
|
type AddEvent = <N extends keyof EventArgsMap>(name: N, listener: OSEventListener<N> | OSEventListener<N>[]) => () => void;
|
||||||
|
type RemoveEvent = <N extends keyof EventArgsMap>(name?: N, listener?: OSEventListener<N> | OSEventListener<N>[]) => void;
|
||||||
interface OverlayScrollbarsStatic {
|
interface OverlayScrollbarsStatic {
|
||||||
(target: OSTarget | OSInitializationObject, options?: PartialOptions<OSOptions>, extensions?: any): OverlayScrollbars;
|
(target: OSTarget | OSInitializationObject, options?: PartialOptions<OSOptions>, extensions?: any): OverlayScrollbars;
|
||||||
extend(osPlugin: OSPlugin | OSPlugin[]): void;
|
extend(osPlugin: OSPlugin | OSPlugin[]): void;
|
||||||
@@ -99,6 +116,8 @@ interface OverlayScrollbars {
|
|||||||
update(force?: boolean): void;
|
update(force?: boolean): void;
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
state(): any;
|
state(): any;
|
||||||
|
on: AddEvent;
|
||||||
|
off: RemoveEvent;
|
||||||
}
|
}
|
||||||
declare const OverlayScrollbars: OverlayScrollbarsStatic;
|
declare const OverlayScrollbars: OverlayScrollbarsStatic;
|
||||||
export { OverlayScrollbars as default };
|
export { OverlayScrollbars as default };
|
||||||
|
|||||||
Reference in New Issue
Block a user