improve event flow

This commit is contained in:
Rene
2022-07-12 12:56:27 +02:00
parent 295f94309f
commit a4482f96d6
16 changed files with 685 additions and 633 deletions
+159 -149
View File
@@ -670,11 +670,11 @@ const createEventListenerHub = t => {
}), e);
return removeEvent.bind(0, t, e);
}
function triggerEvent(t, ...e) {
function triggerEvent(t, e) {
const o = n.get(t);
each(from(o), (t => {
if (e) {
t(e);
if (e && !isEmptyArray(e)) {
t.apply(0, e);
} else {
t();
}
@@ -1048,46 +1048,48 @@ const createStructureSetupElements = t => {
const N = f && elementIsGenerated(z);
const R = f ? L : contents([ P, E, D, z, L ].find((t => false === elementIsGenerated(t))));
const H = P || E;
const F = addDataAttrHost(z, y ? "viewport" : "host");
const k = addClass(D, A);
const V = addClass(E, !y && $);
const B = addClass(P, I);
if (N) {
insertAfter(L, z);
const appendElements = () => {
const t = addDataAttrHost(z, y ? "viewport" : "host");
const n = addClass(D, A);
const o = addClass(E, !y && $);
const s = addClass(P, I);
if (N) {
insertAfter(L, z);
push(j, (() => {
insertAfter(z, L);
removeElements(z);
}));
}
appendChildren(H, R);
appendChildren(z, D);
appendChildren(D || z, !y && E);
appendChildren(E, P);
push(j, (() => {
insertAfter(z, L);
removeElements(z);
t();
removeAttr(E, S);
removeAttr(E, C);
if (elementIsGenerated(P)) {
unwrap(P);
}
if (elementIsGenerated(E)) {
unwrap(E);
}
if (elementIsGenerated(D)) {
unwrap(D);
}
n();
o();
s();
}));
}
appendChildren(H, R);
appendChildren(z, D);
appendChildren(D || z, !y && E);
appendChildren(E, P);
push(j, (() => {
F();
removeAttr(E, S);
removeAttr(E, C);
if (elementIsGenerated(P)) {
unwrap(P);
if (e && !y) {
push(j, removeClass.bind(0, E, T));
}
if (elementIsGenerated(E)) {
unwrap(E);
if (M) {
insertBefore(E, M);
push(j, removeElements.bind(0, M));
}
if (elementIsGenerated(D)) {
unwrap(D);
}
k();
V();
B();
}));
if (e && !y) {
push(j, removeClass.bind(0, E, T));
}
if (M) {
insertBefore(E, M);
push(j, removeElements.bind(0, M));
}
return [ x, runEach.bind(0, j) ];
};
return [ x, appendElements, runEach.bind(0, j) ];
};
const createTrinsicUpdate = (t, n) => {
@@ -2011,29 +2013,27 @@ const ut = {
const createStructureSetup = (t, n) => {
const e = createOptionCheck(n, {});
const o = createState(ut);
const s = new Set;
const [c] = o;
const runOnUpdatedListeners = (t, n, e) => {
runEach(s, [ t, n || {}, !!e ]);
};
const [i, r] = createStructureSetupElements(t);
const a = createStructureSetupUpdate(i, o);
const [l, u] = createStructureSetupObservers(i, o, (t => {
runOnUpdatedListeners(a(e, t));
const [s, c, i] = createEventListenerHub();
const [r] = o;
const [a, l, u] = createStructureSetupElements(t);
const f = createStructureSetupUpdate(a, o);
const [d, _] = createStructureSetupObservers(a, o, (t => {
i("u", [ f(e, t), {}, false ]);
}));
const f = c.bind(0);
f.Pt = t => {
s.add(t);
const g = r.bind(0);
g.Pt = t => {
s("u", t);
};
f.Mt = i;
g.Mt = l;
g.jt = a;
return [ (t, e) => {
const o = createOptionCheck(n, t, e);
l(o);
runOnUpdatedListeners(a(o, {}, e));
}, f, () => {
s.clear();
d(o);
i("u", [ f(o, {}, e), t, !!e ]);
}, g, () => {
c();
_();
u();
r();
} ];
};
@@ -2044,41 +2044,44 @@ const generateScrollbarDOM = t => {
appendChildren(n, e);
appendChildren(e, o);
return {
jt: n,
Nt: e,
Rt: o
Nt: n,
Rt: e,
Ht: o
};
};
const createScrollbarsSetupElements = (t, n) => {
const {N: e} = getEnvironment();
const {Ht: o} = e();
const {Ft: o} = e();
const {Y: s, B: c, U: i, tt: r} = n;
const a = !r && t.scrollbarsSlot;
const l = dynamicInitializationElement([ s, c, i ], (() => c), o, a);
const u = generateScrollbarDOM(F);
const f = generateScrollbarDOM(k);
const {jt: d} = u;
const {jt: _} = f;
appendChildren(l, d);
appendChildren(l, _);
const {Nt: d} = u;
const {Nt: _} = f;
const appendElements = () => {
appendChildren(l, d);
appendChildren(l, _);
};
return [ {
Ft: u,
kt: f
}, removeElements.bind(0, [ d, _ ]) ];
kt: u,
Vt: f
}, appendElements, removeElements.bind(0, [ d, _ ]) ];
};
const createScrollbarsSetup = (t, n, e) => {
const o = createState({});
const [s] = o;
const [c, i] = createScrollbarsSetupElements(t, e);
const r = s.bind(0);
r.Mt = c;
const [c, i, r] = createScrollbarsSetupElements(t, e);
const a = s.bind(0);
a.jt = c;
a.Mt = i;
return [ (t, e) => {
const o = createOptionCheck(n, t, e);
console.log(o);
}, r, () => {
i();
}, a, () => {
r();
} ];
};
@@ -2157,34 +2160,95 @@ const removeInstance = t => {
const getInstance = t => mt.get(t);
const OverlayScrollbars = (t, n, e) => {
const {H: o, I: s, j: c} = getEnvironment();
const i = getPlugins();
const r = isHTMLElement(t) ? t : t.target;
const a = getInstance(r);
if (a) {
return a;
let o = false;
const {H: s, I: c, j: i} = getEnvironment();
const r = getPlugins();
const a = isHTMLElement(t) ? t : t.target;
const l = getInstance(a);
if (l) {
return l;
}
const l = i[bt];
const u = r[bt];
const validateOptions = t => {
const n = t || {};
const e = l && l.Vt;
const e = u && u.Bt;
return e ? e(n, true) : n;
};
const u = assignDeep({}, o(), validateOptions(n));
const [f, d, _] = createEventListenerHub(e);
if (s.x && s.y && !u.nativeScrollbarsOverlaid.initialize) {
_("initializationWithdrawn");
}
const [g, h, p] = createStructureSetup(t, u);
const [v, , w] = createScrollbarsSetup(t, u, h.Mt);
const f = assignDeep({}, s(), validateOptions(n));
const [d, _, g] = createEventListenerHub(e);
const [h, p, v] = createStructureSetup(t, f);
const [w, b, y] = createScrollbarsSetup(t, f, p.jt);
const update = (t, n) => {
g(t, n);
v(t, n);
h(t, n);
w(t, n);
};
const b = c(update.bind(0, {}, true));
h.Pt(((t, n, e) => {
const m = i(update.bind(0, {}, true));
const destroy = t => {
removeInstance(a);
m();
y();
v();
o = true;
g("destroyed", [ S, !!t ]);
_();
};
const S = {
options(t) {
if (t) {
const n = getOptionsDiff(f, validateOptions(t));
if (!isEmptyObject(n)) {
assignDeep(f, n);
update(n);
}
}
return assignDeep({}, f);
},
on: d,
off: _,
state() {
const {yt: t, vt: n, St: e, A: s, ft: c} = p();
return assignDeep({}, {
overflowAmount: t,
overflowStyle: n,
hasOverflow: e,
padding: s,
paddingAbsolute: c,
destroyed: o
});
},
elements() {
const {Y: t, B: n, A: e, U: o, $: s} = p.jt;
return assignDeep({}, {
target: t,
host: n,
padding: e || o,
viewport: o,
content: s || o
});
},
update(t) {
update({}, t);
return S;
},
destroy: destroy.bind(0)
};
if (c.x && c.y && !f.nativeScrollbarsOverlaid.initialize) {
destroy(true);
return S;
}
each(keys(r), (t => {
const n = r[t];
if (isFunction(n)) {
n(OverlayScrollbars, S);
}
}));
p.Mt();
b.Mt();
addInstance(a, S);
g("initialized", [ S ]);
p.Pt(((t, n, e) => {
const {it: o, ut: s, ct: c, xt: i, Ct: r, rt: a, bt: l} = t;
_("updated", {
g("updated", [ S, {
updateHints: {
sizeChanged: o,
directionChanged: s,
@@ -2196,63 +2260,9 @@ const OverlayScrollbars = (t, n, e) => {
},
changedOptions: n,
force: e
});
} ]);
}));
const y = {
options(t) {
if (t) {
const n = getOptionsDiff(u, validateOptions(t));
if (!isEmptyObject(n)) {
assignDeep(u, n);
update(n);
}
}
return assignDeep({}, u);
},
on: f,
off: d,
state() {
const {yt: t, vt: n, St: e, A: o, ft: s} = h();
return assignDeep({}, {
overflowAmount: t,
overflowStyle: n,
hasOverflow: e,
padding: o,
paddingAbsolute: s
});
},
elements() {
const {Y: t, B: n, A: e, U: o, $: s} = h.Mt;
return assignDeep({}, {
target: t,
host: n,
padding: e || o,
viewport: o,
content: s || o
});
},
update(t) {
update({}, t);
},
destroy: () => {
removeInstance(r);
b();
d();
w();
p();
_("destroyed");
}
};
each(keys(i), (t => {
const n = i[t];
if (isFunction(n)) {
n(OverlayScrollbars, y);
}
}));
y.update(true);
addInstance(r, y);
_("initialized");
return y;
return S.update(true);
};
OverlayScrollbars.plugin = addPlugin;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -31,17 +31,6 @@ import type {
EventListener as GeneralEventListener,
} from 'support/eventListeners';
/*
onScrollStart : null,
onScroll : null,
onScrollStop : null,
onOverflowChanged : null,
onOverflowAmountChanged : null, // fusion with onOverflowChanged
onDirectionChanged : null, // gone
onContentSizeChanged : null, // gone
onHostSizeChanged : null, // gone
*/
export interface OverlayScrollbarsStatic {
(
target: InitializationTarget | InitializationTargetObject,
@@ -75,6 +64,7 @@ export interface State {
overflowAmount: XY<number>;
overflowStyle: XY<OverflowStyle>;
hasOverflow: XY<boolean>;
destroyed: boolean;
}
export interface Elements {
@@ -100,10 +90,18 @@ export interface OnUpdatedEventListenerArgs {
}
export type EventListenerMap = {
initialized: [];
initializationWithdrawn: [];
updated: [OnUpdatedEventListenerArgs];
destroyed: [];
/**
* Triggered after all elements are initialized and appended.
*/
initialized: [instance: OverlayScrollbars];
/**
* Triggered after an update.
*/
updated: [instance: OverlayScrollbars, onUpdatedArgs: OnUpdatedEventListenerArgs];
/**
* Triggered after all elements, observers and events are destroyed.
*/
destroyed: [instance: OverlayScrollbars, withdrawn: boolean];
};
export type InitialEventListeners = GeneralInitialEventListeners<EventListenerMap>;
@@ -117,7 +115,7 @@ export interface OverlayScrollbars {
options(): Options;
options(newOptions?: PartialOptions<Options>): Options;
update(force?: boolean): void;
update(force?: boolean): OverlayScrollbars;
destroy(): void;
@@ -142,6 +140,7 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
options?,
eventListeners?
): OverlayScrollbars => {
let destroyed = false;
const {
_getDefaultOptions,
_nativeScrollbarIsOverlaid,
@@ -168,59 +167,33 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
validateOptions(options)
);
const [addEvent, removeEvent, triggerEvent] = createEventListenerHub(eventListeners);
if (
_nativeScrollbarIsOverlaid.x &&
_nativeScrollbarIsOverlaid.y &&
!currentOptions.nativeScrollbarsOverlaid.initialize
) {
triggerEvent('initializationWithdrawn');
}
const [updateStructure, structureState, destroyStructure] = createStructureSetup(
target,
currentOptions
);
const [updateScrollbars, , destroyScrollbars] = createScrollbarsSetup(
const [updateScrollbars, scrollbarsState, destroyScrollbars] = createScrollbarsSetup(
target,
currentOptions,
structureState._elements
);
const update = (changedOptions: PartialOptions<Options>, force?: boolean) => {
updateStructure(changedOptions, force);
updateScrollbars(changedOptions, force);
};
const removeEnvListener = addEnvListener(update.bind(0, {}, true));
const destroy = (withdrawn?: boolean) => {
removeInstance(instanceTarget);
removeEnvListener();
structureState._addOnUpdatedListener((updateHints, changedOptions, force) => {
const {
_sizeChanged,
_directionChanged,
_heightIntrinsicChanged,
_overflowAmountChanged,
_overflowStyleChanged,
_contentMutation,
_hostMutation,
} = updateHints;
destroyScrollbars();
destroyStructure();
triggerEvent('updated', [
{
updateHints: {
sizeChanged: _sizeChanged,
directionChanged: _directionChanged,
heightIntrinsicChanged: _heightIntrinsicChanged,
overflowAmountChanged: _overflowAmountChanged,
overflowStyleChanged: _overflowStyleChanged,
contentMutation: _contentMutation,
hostMutation: _hostMutation,
},
changedOptions,
force,
},
]);
});
destroyed = true;
// eslint-disable-next-line no-use-before-define
triggerEvent('destroyed', [instance, !!withdrawn]);
removeEvent();
};
const instance: OverlayScrollbars = {
options(newOptions?: PartialOptions<Options>) {
@@ -235,7 +208,9 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
return assignDeep({}, currentOptions);
},
on: addEvent,
off: removeEvent,
off: (name, listener) => {
name && listener && removeEvent(name, listener as any);
},
state() {
const { _overflowAmount, _overflowStyle, _hasOverflow, _padding, _paddingAbsolute } =
structureState();
@@ -247,6 +222,7 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
hasOverflow: _hasOverflow,
padding: _padding,
paddingAbsolute: _paddingAbsolute,
destroyed,
}
);
},
@@ -265,17 +241,9 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
},
update(force?: boolean) {
update({}, force);
return instance;
},
destroy: () => {
removeInstance(instanceTarget);
removeEnvListener();
removeEvent();
destroyScrollbars();
destroyStructure();
triggerEvent('destroyed');
},
destroy: destroy.bind(0),
};
each(keys(plugins), (pluginName) => {
@@ -285,13 +253,51 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
}
});
instance.update(true);
if (
_nativeScrollbarIsOverlaid.x &&
_nativeScrollbarIsOverlaid.y &&
!currentOptions.nativeScrollbarsOverlaid.initialize
) {
destroy(true);
return instance;
}
structureState._appendElements();
scrollbarsState._appendElements();
addInstance(instanceTarget, instance);
triggerEvent('initialized', [instance]);
triggerEvent('initialized');
structureState._addOnUpdatedListener((updateHints, changedOptions, force) => {
const {
_sizeChanged,
_directionChanged,
_heightIntrinsicChanged,
_overflowAmountChanged,
_overflowStyleChanged,
_contentMutation,
_hostMutation,
} = updateHints;
return instance;
triggerEvent('updated', [
instance,
{
updateHints: {
sizeChanged: _sizeChanged,
directionChanged: _directionChanged,
heightIntrinsicChanged: _heightIntrinsicChanged,
overflowAmountChanged: _overflowAmountChanged,
overflowStyleChanged: _overflowStyleChanged,
contentMutation: _contentMutation,
hostMutation: _hostMutation,
},
changedOptions,
force,
},
]);
});
return instance.update(true);
};
OverlayScrollbars.plugin = addPlugin;
@@ -1 +0,0 @@
export { optionsValidationPlugin } from 'plugins/optionsValidation/optionsValidation';
@@ -27,7 +27,11 @@ export interface ScrollbarsSetupElementsObj {
_verticalScrollbarStructure: ScrollbarStructure;
}
export type ScrollbarsSetupElements = [elements: ScrollbarsSetupElementsObj, destroy: () => void];
export type ScrollbarsSetupElements = [
elements: ScrollbarsSetupElementsObj,
appendElements: () => void,
destroy: () => void
];
const generateScrollbarDOM = (scrollbarClassName: string): ScrollbarStructure => {
const scrollbar = createDiv(`${classNameScrollbar} ${scrollbarClassName}`);
@@ -68,14 +72,17 @@ export const createScrollbarsSetupElements = (
const { _scrollbar: horizontalScrollbar } = horizontalScrollbarStructure;
const { _scrollbar: verticalScrollbar } = verticalScrollbarStructure;
appendChildren(evaluatedScrollbarSlot, horizontalScrollbar);
appendChildren(evaluatedScrollbarSlot, verticalScrollbar);
const appendElements = () => {
appendChildren(evaluatedScrollbarSlot, horizontalScrollbar);
appendChildren(evaluatedScrollbarSlot, verticalScrollbar);
};
return [
{
_horizontalScrollbarStructure: horizontalScrollbarStructure,
_verticalScrollbarStructure: verticalScrollbarStructure,
},
appendElements,
removeElements.bind(0, [horizontalScrollbar, verticalScrollbar]),
];
};
@@ -13,6 +13,7 @@ export interface ScrollbarsSetupState {}
export interface ScrollbarsSetupStaticState {
_elements: ScrollbarsSetupElementsObj;
_appendElements: () => void;
}
export const createScrollbarsSetup = (
@@ -23,11 +24,15 @@ export const createScrollbarsSetup = (
const state = createState({});
const [getState] = state;
const [elements, destroyElements] = createScrollbarsSetupElements(target, structureSetupElements);
const [elements, appendElements, destroyElements] = createScrollbarsSetupElements(
target,
structureSetupElements
);
const scrollbarsSetupState = getState.bind(0) as (() => ScrollbarsSetupState) &
ScrollbarsSetupStaticState;
scrollbarsSetupState._elements = elements;
scrollbarsSetupState._appendElements = appendElements;
return [
(changedOptions, force?) => {
@@ -43,7 +43,11 @@ import type {
StructureStaticInitializationElement,
} from 'setups/structureSetup/structureSetup.initialization';
export type StructureSetupElements = [targetObj: StructureSetupElementsObj, destroy: () => void];
export type StructureSetupElements = [
targetObj: StructureSetupElementsObj,
appendElements: () => void,
destroy: () => void
];
export interface StructureSetupElementsObj {
_target: InitializationTargetElement;
@@ -197,52 +201,54 @@ export const createStructureSetupElements = (
)
);
const contentSlot = _content || _viewport;
const removeHostDataAttr = addDataAttrHost(_host, viewportIsTarget ? 'viewport' : 'host');
const removePaddingClass = addClass(_padding, classNamePadding);
const removeViewportClass = addClass(_viewport, !viewportIsTarget && classNameViewport);
const removeContentClass = addClass(_content, classNameContent);
const appendElements = () => {
const removeHostDataAttr = addDataAttrHost(_host, viewportIsTarget ? 'viewport' : 'host');
const removePaddingClass = addClass(_padding, classNamePadding);
const removeViewportClass = addClass(_viewport, !viewportIsTarget && classNameViewport);
const removeContentClass = addClass(_content, classNameContent);
// only insert host for textarea after target if it was generated
if (isTextareaHostGenerated) {
insertAfter(_target, _host);
// only insert host for textarea after target if it was generated
if (isTextareaHostGenerated) {
insertAfter(_target, _host);
push(destroyFns, () => {
insertAfter(_host, _target);
removeElements(_host);
});
}
appendChildren(contentSlot, targetContents);
appendChildren(_host, _padding);
appendChildren(_padding || _host, !viewportIsTarget && _viewport);
appendChildren(_viewport, _content);
push(destroyFns, () => {
insertAfter(_host, _target);
removeElements(_host);
removeHostDataAttr();
removeAttr(_viewport, dataAttributeHostOverflowX);
removeAttr(_viewport, dataAttributeHostOverflowY);
if (elementIsGenerated(_content)) {
unwrap(_content);
}
if (elementIsGenerated(_viewport)) {
unwrap(_viewport);
}
if (elementIsGenerated(_padding)) {
unwrap(_padding);
}
removePaddingClass();
removeViewportClass();
removeContentClass();
});
}
appendChildren(contentSlot, targetContents);
appendChildren(_host, _padding);
appendChildren(_padding || _host, !viewportIsTarget && _viewport);
appendChildren(_viewport, _content);
push(destroyFns, () => {
removeHostDataAttr();
removeAttr(_viewport, dataAttributeHostOverflowX);
removeAttr(_viewport, dataAttributeHostOverflowY);
if (elementIsGenerated(_content)) {
unwrap(_content);
if (_nativeScrollbarStyling && !viewportIsTarget) {
push(destroyFns, removeClass.bind(0, _viewport, classNameViewportScrollbarStyling));
}
if (elementIsGenerated(_viewport)) {
unwrap(_viewport);
if (_viewportArrange) {
insertBefore(_viewport, _viewportArrange);
push(destroyFns, removeElements.bind(0, _viewportArrange));
}
if (elementIsGenerated(_padding)) {
unwrap(_padding);
}
removePaddingClass();
removeViewportClass();
removeContentClass();
});
};
if (_nativeScrollbarStyling && !viewportIsTarget) {
push(destroyFns, removeClass.bind(0, _viewport, classNameViewportScrollbarStyling));
}
if (_viewportArrange) {
insertBefore(_viewport, _viewportArrange);
push(destroyFns, removeElements.bind(0, _viewportArrange));
}
return [evaluatedTargetObj, runEach.bind(0, destroyFns)];
return [evaluatedTargetObj, appendElements, runEach.bind(0, destroyFns)];
};
@@ -1,11 +1,11 @@
import { runEach } from 'support';
import { createEventListenerHub } from 'support';
import { createState, createOptionCheck } from 'setups/setups';
import { createStructureSetupElements } from 'setups/structureSetup/structureSetup.elements';
import { createStructureSetupUpdate } from 'setups/structureSetup/structureSetup.update';
import { createStructureSetupObservers } from 'setups/structureSetup/structureSetup.observers';
import type { StructureSetupUpdateHints } from 'setups/structureSetup/structureSetup.update';
import type { StructureSetupElementsObj } from 'setups/structureSetup/structureSetup.elements';
import type { TRBL, XY } from 'support';
import type { TRBL, XY, EventListener } from 'support';
import type { Options, ReadonlyOSOptions } from 'options';
import type { Setup } from 'setups';
import type { InitializationTarget } from 'initialization';
@@ -24,14 +24,17 @@ export interface StructureSetupState {
export interface StructureSetupStaticState {
_elements: StructureSetupElementsObj;
_addOnUpdatedListener: (listener: OnUpdatedListener) => void;
_appendElements: () => void;
_addOnUpdatedListener: (listener: EventListener<StructureSetupEventMap, 'u'>) => void;
}
export type OnUpdatedListener = (
updateHints: StructureSetupUpdateHints,
changedOptions: PartialOptions<Options>,
force: boolean
) => void;
type StructureSetupEventMap = {
u: [
updateHints: StructureSetupUpdateHints,
changedOptions: PartialOptions<Options>,
force: boolean
];
};
const initialStructureSetupUpdateState: StructureSetupState = {
_padding: {
@@ -72,42 +75,35 @@ export const createStructureSetup = (
): Setup<StructureSetupState, StructureSetupStaticState> => {
const checkOptionsFallback = createOptionCheck(options, {});
const state = createState(initialStructureSetupUpdateState);
const onUpdatedListeners = new Set<OnUpdatedListener>();
const [addEvent, removeEvent, triggerEvent] = createEventListenerHub<StructureSetupEventMap>();
const [getState] = state;
const runOnUpdatedListeners = (
updateHints: StructureSetupUpdateHints,
changedOptions?: PartialOptions<Options>,
force?: boolean
) => {
runEach(onUpdatedListeners, [updateHints, changedOptions || {}, !!force]);
};
const [elements, destroyElements] = createStructureSetupElements(target);
const [elements, appendElements, destroyElements] = createStructureSetupElements(target);
const updateStructure = createStructureSetupUpdate(elements, state);
const [updateObservers, destroyObservers] = createStructureSetupObservers(
elements,
state,
(updateHints) => {
runOnUpdatedListeners(updateStructure(checkOptionsFallback, updateHints));
triggerEvent('u', [updateStructure(checkOptionsFallback, updateHints), {}, false]);
}
);
const structureSetupState = getState.bind(0) as (() => StructureSetupState) &
StructureSetupStaticState;
structureSetupState._addOnUpdatedListener = (listener) => {
onUpdatedListeners.add(listener);
addEvent('u', listener);
};
structureSetupState._appendElements = appendElements;
structureSetupState._elements = elements;
return [
(changedOptions, force?) => {
const checkOption = createOptionCheck(options, changedOptions, force);
updateObservers(checkOption);
runOnUpdatedListeners(updateStructure(checkOption, {}, force));
triggerEvent('u', [updateStructure(checkOption, {}, force), changedOptions, !!force]);
},
structureSetupState,
() => {
onUpdatedListeners.clear();
removeEvent();
destroyObservers();
destroyElements();
},
@@ -115,7 +115,8 @@ const assertCorrectDOMStructure = (textarea: boolean, viewportIsTarget: boolean)
const createStructureSetupProxy = (
target: InitializationTarget | StructureInitialization
): StructureSetupElementsProxy => {
const [elements, destroy] = createStructureSetupElements(target);
const [elements, appendElements, destroy] = createStructureSetupElements(target);
appendElements();
return {
input: target,
elements,
@@ -7,8 +7,11 @@ import { timeout } from '@/testing-browser/timeout';
import { setTestResult, waitForOrFailTest } from '@/testing-browser/TestResult';
import { addClass, each, isArray, removeAttr, style } from 'support';
// @ts-ignore
window.OverlayScrollbars = OverlayScrollbars;
OverlayScrollbars.env().setDefaultOptions({
nativeScrollbarsOverlaid: { initialize: true },
nativeScrollbarsOverlaid: { initialize: false },
});
const startBtn: HTMLButtonElement | null = document.querySelector('#start');
@@ -33,6 +36,7 @@ let rootUpdateCount = 0;
let aUpdateCount = 0;
let bUpdateCount = 0;
let cUpdateCount = 0;
const rootInstance = OverlayScrollbars(
{ target: targetRoot!, padding: true },
{},
@@ -25,6 +25,13 @@ import { timeout } from '@/testing-browser/timeout';
import { Options } from 'options';
import { PartialOptions } from 'typings';
// @ts-ignore
window.OverlayScrollbars = OverlayScrollbars;
OverlayScrollbars.env().setDefaultOptions({
nativeScrollbarsOverlaid: { initialize: true },
});
interface Metrics {
offset: {
left: number;
@@ -122,7 +129,7 @@ const osInstance =
// @ts-ignore
(window.os = OverlayScrollbars(
initObj,
{ nativeScrollbarsOverlaid: { initialize: true } },
{},
{
updated() {
updateCount++;
+28 -24
View File
@@ -12,11 +12,8 @@ interface XY<T> {
x: T;
y: T;
}
type EventListener<EventMap extends Record<string, any>, Name extends keyof EventMap> = (...args: EventMap[Name] extends undefined ? [
] : [
args: EventMap[Name]
]) => void;
type InitialEventListeners<EventMap extends Record<string, any>> = {
type EventListener<EventMap extends Record<string, any[]>, Name extends keyof EventMap> = (...args: EventMap[Name]) => void;
type InitialEventListeners<EventMap extends Record<string, any[]>> = {
[K in keyof EventMap]?: EventListener<EventMap> | EventListener<EventMap>[];
};
type OverflowBehavior = "hidden" | "scroll" | "visible" | "visible-hidden" | "visible-scroll";
@@ -125,16 +122,6 @@ type DynamicInitializationElement<Args extends any[]> = ((...args: Args) => Dyna
type InitializtationElementStrategy<InitElm> = Exclude<InitElm, HTMLElement>;
type GeneralInitialEventListeners = InitialEventListeners;
type GeneralEventListener = EventListener;
/*
onScrollStart : null,
onScroll : null,
onScrollStop : null,
onOverflowChanged : null,
onOverflowAmountChanged : null, // fusion with onOverflowChanged
onDirectionChanged : null, // gone
onContentSizeChanged : null, // gone
onHostSizeChanged : null, // gone
*/
interface OverlayScrollbarsStatic {
(target: InitializationTarget | InitializationTargetObject, options?: PartialOptions<Options>, eventListeners?: GeneralInitialEventListeners<EventListenerMap>): OverlayScrollbars;
plugin(osPlugin: OSPlugin | OSPlugin[]): void;
@@ -163,6 +150,7 @@ interface State {
overflowAmount: XY<number>;
overflowStyle: XY<OverflowStyle>;
hasOverflow: XY<boolean>;
destroyed: boolean;
}
interface Elements {
target: HTMLElement;
@@ -184,24 +172,40 @@ interface OnUpdatedEventListenerArgs {
changedOptions: PartialOptions<Options>;
force: boolean;
}
interface EventListenerMap {
initialized: undefined;
initializationWithdrawn: undefined;
updated: OnUpdatedEventListenerArgs;
destroyed: undefined;
}
type EventListenerMap = {
/**
* Triggered after all elements are initialized and appended.
*/
initialized: [
instance: OverlayScrollbars
];
/**
* Triggered after an update.
*/
updated: [
instance: OverlayScrollbars,
onUpdatedArgs: OnUpdatedEventListenerArgs
];
/**
* Triggered after all elements, observers and events are destroyed.
*/
destroyed: [
instance: OverlayScrollbars,
withdrawn: boolean
];
};
type EventListener$0<Name extends keyof EventListenerMap> = GeneralEventListener<EventListenerMap, Name>;
interface OverlayScrollbars {
options(): Options;
options(newOptions?: PartialOptions<Options>): Options;
update(force?: boolean): void;
update(force?: boolean): OverlayScrollbars;
destroy(): void;
state(): State;
elements(): Elements;
on<Name extends keyof EventListenerMap>(name: Name, listener: EventListener$0<Name>): () => void;
on<Name extends keyof EventListenerMap>(name: Name, listener: EventListener$0<Name>[]): () => void;
off<Name extends keyof EventListenerMap>(name: Name, listener?: EventListener$0<Name>): void;
off<Name extends keyof EventListenerMap>(name: Name, listener?: EventListener$0<Name>[]): void;
off<Name extends keyof EventListenerMap>(name: Name, listener: EventListener$0<Name>): void;
off<Name extends keyof EventListenerMap>(name: Name, listener: EventListener$0<Name>[]): void;
}
/**
* Notes: