Skip to content

Commit

Permalink
0.12.0-2
Browse files Browse the repository at this point in the history
  • Loading branch information
Norman Rusch committed Sep 22, 2021
1 parent 778a827 commit f42862d
Show file tree
Hide file tree
Showing 27 changed files with 442 additions and 368 deletions.
7 changes: 3 additions & 4 deletions dist/caroucssel.d.ts → dist/carousel.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Index, Options, Pages, ScrollBehavior } from './types';
export * from './types';
import { ICarousel, Index, Options, Pages, ScrollBehavior } from './types';
/**
* The carousel javascript instance.
*/
export declare class Carousel {
export declare class Carousel implements ICarousel {
/**
* This can be used for testing purposes to reset the instance count which is
* This will be used for testing purposes to reset the instance count which is
* used to create unique id's.
* @internal
*/
Expand Down
115 changes: 35 additions & 80 deletions dist/caroucssel.js → dist/carousel.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Mask } from './plugins/mask';
import { Mask } from './features/mask';
import { Proxy } from './proxy';
import { ScrollBehavior, UpdateReason } from './types';
import { clearCache, clearFullCache, fromCache, writeCache } from './utils/cache';
import { debounce } from './utils/debounce';
// Export all types
// (is required to expose all types in dist/caroucssel.d.ts)
export * from './types';
const ID_NAME = (count) => `caroucssel-${count}`;
const ID_MATCH = /^caroucssel-[0-9]*$/;
const EVENT_SCROLL = 'scroll';
const EVENT_RESIZE = 'resize';
const CACHE_KEY_ELEMENT = 'element';
const CACHE_KEY_ID = 'id';
const CACHE_KEY_CONFIGURATION = 'config';
Expand All @@ -16,66 +16,18 @@ const CACHE_KEY_PAGES = 'pages';
const CACHE_KEY_PAGE_INDEX = 'page-index';
const CACHE_KEY_MASK = 'mask';
const CACHE_KEY_PROXY = 'proxy';
const CACHE_KEY_PLUGINS = 'plugins';
const CACHE_KEY_PROXY_INSTANCE = 'proxy:instance';
const CACHE_KEY_PROXY_PLUGIN = 'proxy:plugins';
const CACHE_KEY_FEATURES = 'feautres';
const VISIBILITY_OFFSET = 0.25;
const INVISIBLE_ELEMENTS = /^(link|meta|noscript|script|style|title)$/i;
const EVENT_SCROLL = 'scroll';
const EVENT_RESIZE = 'resize';
const DEFAULTS = {
// Plugins:
plugins: [],
// filter
features: [],
filterItem: () => true,
// Hooks:
onScroll: () => undefined,
};
/*
* Internal counter for created instances. Will be used to create unique IDs.
*/
let __instanceCount = 0;
/**
* A proxy instance between carousel and each plugin.
*/
class Proxy {
constructor(instance, plugins) {
writeCache(this, CACHE_KEY_PROXY_INSTANCE, instance);
writeCache(this, CACHE_KEY_PROXY_PLUGIN, plugins);
}
get el() {
const instance = fromCache(this, CACHE_KEY_PROXY_INSTANCE);
return instance.el;
}
get mask() {
const instance = fromCache(this, CACHE_KEY_PROXY_INSTANCE);
return instance.mask;
}
get index() {
const instance = fromCache(this, CACHE_KEY_PROXY_INSTANCE);
return instance.index;
}
set index(value) {
const instance = fromCache(this, CACHE_KEY_PROXY_INSTANCE);
instance.index = value;
}
get items() {
const instance = fromCache(this, CACHE_KEY_PROXY_INSTANCE);
return instance.items;
}
get pages() {
const instance = fromCache(this, CACHE_KEY_PROXY_INSTANCE);
return instance.pages;
}
get pageIndex() {
const instance = fromCache(this, CACHE_KEY_PROXY_INSTANCE);
return instance.pageIndex;
}
update(plugin) {
// @TODO: Trigger update in instance and all other plugins except the source
// plugin that triggered the event.
}
}
/**
* The carousel javascript instance.
*/
Expand Down Expand Up @@ -105,22 +57,26 @@ export class Carousel {
// Extend options and defaults into configuration:
const configuration = Object.assign(Object.assign({}, DEFAULTS), options);
writeCache(this, CACHE_KEY_CONFIGURATION, configuration);
// Detect if there is a "Mask" plugin passed as option. Then use this one,
// otherwise add a mandatory instance by default:
const plugins = [...configuration.plugins];
const index = configuration.plugins.findIndex((plugin) => plugin instanceof Mask);
let mask = new Mask();
// Detect if there is a "Mask" feature passed as option. Then use this one,
// otherwise add a mandatory instance by default. Also ensure that only one
// feature of type "Mask" is in the features list.
let mask = null;
let features = [...configuration.features];
const index = configuration.features.findIndex((feature) => feature instanceof Mask);
if (index > -1) {
[mask] = plugins.splice(index, 1);
// Extract first found instance of "Mask":
[mask] = features.splice(index, 1);
}
plugins.unshift(mask);
mask !== null && mask !== void 0 ? mask : (mask = new Mask());
features = features.filter((feature) => !(feature instanceof Mask));
features = [mask, ...features];
writeCache(this, CACHE_KEY_MASK, mask);
// Plugins:
const proxy = new Proxy(this, plugins);
// Features: Initialize all features with a single proxy instance inbetween.
const proxy = new Proxy(this, features);
writeCache(this, CACHE_KEY_PROXY, proxy);
writeCache(this, CACHE_KEY_PLUGINS, plugins);
plugins.forEach((plugin) => plugin.init(proxy));
// Set initial index and set smooth scrolling:
writeCache(this, CACHE_KEY_FEATURES, features);
features.forEach((feature) => feature.init(proxy));
// Set initial index and finally set smooth scrolling to enabled:
switch (true) {
// When index is a list:
case Array.isArray(options.index):
Expand All @@ -147,11 +103,13 @@ export class Carousel {
/* eslint-enable @typescript-eslint/unbound-method */
}
/**
* This can be used for testing purposes to reset the instance count which is
* This will be used for testing purposes to reset the instance count which is
* used to create unique id's.
* @internal
*/
static resetInstanceCount() {
/* This should not be part of the coverage report: test util */
/* istanbul ignore next */
if (process.env.NODE_ENV === 'test') {
__instanceCount = 0;
}
Expand Down Expand Up @@ -230,9 +188,6 @@ export class Carousel {
if (!Array.isArray(values) || !values.length) {
return;
}
if (length === 0) {
return;
}
let value = values[0] || 0;
value = Math.max(Math.min(value, length - 1), 0);
const { scrollLeft } = el;
Expand Down Expand Up @@ -389,9 +344,9 @@ export class Carousel {
const { el } = this;
// Remove created id if it was created by carousel:
ID_MATCH.test(el.id) && el.removeAttribute('id');
// Destroy attached plugins:
const plugins = fromCache(this, CACHE_KEY_PLUGINS);
plugins === null || plugins === void 0 ? void 0 : plugins.forEach((plugin) => plugin.destroy());
// Destroy attached features:
const features = fromCache(this, CACHE_KEY_FEATURES);
features.forEach((feature) => feature.destroy());
// Remove events:
//
// We need to work the the function reference. Using .bind() would create a
Expand All @@ -415,23 +370,23 @@ export class Carousel {
clearCache(this, CACHE_KEY_ITEMS);
clearCache(this, CACHE_KEY_PAGES);
clearCache(this, CACHE_KEY_PAGE_INDEX);
const plugins = fromCache(this, CACHE_KEY_PLUGINS);
plugins === null || plugins === void 0 ? void 0 : plugins.forEach((plugin) => plugin.update({ reason: UpdateReason.FORCED }));
const features = fromCache(this, CACHE_KEY_FEATURES);
features.forEach((feature) => feature.update({ reason: UpdateReason.FORCED }));
}
_onScroll(event) {
clearCache(this, CACHE_KEY_INDEX);
clearCache(this, CACHE_KEY_PAGE_INDEX);
const plugins = fromCache(this, CACHE_KEY_PLUGINS);
plugins === null || plugins === void 0 ? void 0 : plugins.forEach((plugin) => plugin.update({ reason: UpdateReason.SCROLL }));
const features = fromCache(this, CACHE_KEY_FEATURES);
features.forEach((feature) => feature.update({ reason: UpdateReason.SCROLL }));
const { index } = this;
const configuration = fromCache(this, CACHE_KEY_CONFIGURATION);
configuration === null || configuration === void 0 ? void 0 : configuration.onScroll({ index, type: EVENT_SCROLL, target: this, originalEvent: event });
configuration.onScroll({ index, type: EVENT_SCROLL, target: this, originalEvent: event });
}
_onResize() {
clearCache(this, CACHE_KEY_PAGES);
clearCache(this, CACHE_KEY_INDEX);
clearCache(this, CACHE_KEY_PAGE_INDEX);
const plugins = fromCache(this, CACHE_KEY_PLUGINS);
plugins === null || plugins === void 0 ? void 0 : plugins.forEach((plugin) => plugin.update({ reason: UpdateReason.RESIZE }));
const features = fromCache(this, CACHE_KEY_FEATURES);
features.forEach((feature) => feature.update({ reason: UpdateReason.RESIZE }));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Plugin, PluginProxy } from '../../types';
import { IFeature, IProxy } from '../../types';
export declare type Params = {
controls: string;
className: string;
Expand All @@ -17,12 +17,12 @@ export declare type Configuration = {
previousTitle: string;
};
/**
* The plugin to enable button controls.
* The feature to enable button controls.
*/
export declare class Buttons implements Plugin {
export declare class Buttons implements IFeature {
constructor(options?: Partial<Configuration>);
get name(): string;
init(proxy: PluginProxy): void;
init(proxy: IProxy): void;
destroy(): void;
update(): void;
private _render;
Expand Down
13 changes: 9 additions & 4 deletions dist/plugins/buttons/index.js → dist/features/buttons/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const CACHE_KEY_PROXY = 'proxy';
const CACHE_KEY_CONFIGURATION = 'config';
const CACHE_KEY_BUTTONS = 'buttons';
/**
* The plugin to enable button controls.
* The feature to enable button controls.
*/
export class Buttons {
constructor(options = {}) {
Expand Down Expand Up @@ -64,6 +64,8 @@ export class Buttons {
label: nextLabel,
title: nextTitle,
className: [className, nextClassName].join(' '),
// The onClick listener was already bound in the constructor.
//
// eslint-disable-next-line @typescript-eslint/unbound-method
handler: this._onNext,
},
Expand All @@ -72,6 +74,8 @@ export class Buttons {
label: previousLabel,
title: previousTitle,
className: [className, previousClassName].join(' '),
// The onClick listener was already bound in the constructor.
//
// eslint-disable-next-line @typescript-eslint/unbound-method
handler: this._onPrevious,
},
Expand Down Expand Up @@ -100,13 +104,14 @@ export class Buttons {
}
_remove() {
const buttons = fromCache(this, CACHE_KEY_BUTTONS);
if (!buttons) {
return;
}
buttons.forEach((button) => {
var _a;
// The onClick listener was already bound in the constructor.
//
// eslint-disable-next-line @typescript-eslint/unbound-method
button === null || button === void 0 ? void 0 : button.removeEventListener('click', this._onPrevious);
// The onClick listener was already bound in the constructor.
//
// eslint-disable-next-line @typescript-eslint/unbound-method
button === null || button === void 0 ? void 0 : button.removeEventListener('click', this._onNext);
(_a = button === null || button === void 0 ? void 0 : button.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(button);
Expand Down
20 changes: 20 additions & 0 deletions dist/features/mask/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { IFeature, IProxy, UpdateData } from '../../types';
export declare type Configuration = {
enabled: boolean;
className: string;
tagName: string;
};
/**
* The feature to enable/disabled mask and scrollbar features. This feature will
* be added by default to each carousel. Use this feature to customize the default behaviour.
*/
export declare class Mask implements IFeature {
constructor(options?: Partial<Configuration>);
get name(): string;
get el(): Element | null;
init(proxy: IProxy): void;
destroy(): void;
update(data: UpdateData): void;
private _render;
private _remove;
}
21 changes: 9 additions & 12 deletions dist/plugins/mask/index.js → dist/features/mask/index.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import { UpdateReason } from '../../types';
import { clearCache, clearFullCache, fromCache, writeCache } from '../../utils/cache';
import { Scrollbar } from '../../utils/scrollbar';
import { Scrollbar } from './scrollbar';
/*
* Singleton of scrollbar util. Is shared across all instances of carousel to
* reduce redundant calculations.
*/
let __scrollbar;
const DEFAULTS = {
enabled: true,
// @TODO: customize class name
// className: 'caroucssel-mask',
// @TODO: customize tag name
// tagName: 'div',
className: 'caroucssel-mask',
tagName: 'div',
};
const CLASSNAME = 'caroucssel-mask';
const CACHE_KEY_PROXY = 'proxy';
const CACHE_KEY_CONFIGURATION = 'config';
const CACHE_KEY_MASK = 'mask';
const CACHE_KEY_HEIGHT = 'scrollbar';
/**
* The plugin to enable/disabled mask and scrollbar features. This plugin will
* be added by default to each carousel. Use this plugin to customize the default behaviour.
* The feature to enable/disabled mask and scrollbar features. This feature will
* be added by default to each carousel. Use this feature to customize the default behaviour.
*/
export class Mask {
constructor(options = {}) {
Expand Down Expand Up @@ -56,7 +53,7 @@ export class Mask {
}
}
_render() {
const { enabled } = fromCache(this, CACHE_KEY_CONFIGURATION);
const { enabled, className, tagName } = fromCache(this, CACHE_KEY_CONFIGURATION);
if (!enabled) {
return;
}
Expand All @@ -69,11 +66,11 @@ export class Mask {
// case, the scrollbar height is 0:
height = 0;
}
// Use from cache factory to render mask element only once:
// Use fromCache factory to render mask element only once:
fromCache(this, CACHE_KEY_MASK, () => {
var _a;
const mask = document.createElement('div');
mask.className = CLASSNAME;
const mask = document.createElement(tagName);
mask.className = className;
mask.style.overflow = 'hidden';
mask.style.height = '100%';
(_a = element.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(mask, element);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export declare type ScrollbarDimensions = {
export declare class Scrollbar {
/**
* Creates an instance.
* @internal
*/
constructor();
/**
Expand Down
3 changes: 2 additions & 1 deletion dist/utils/scrollbar.js → dist/features/mask/scrollbar.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { clearCache, fromCache } from './cache';
import { clearCache, fromCache } from '../../utils/cache';
/**
* Helper class for scrollbar features.
*/
export class Scrollbar {
/**
* Creates an instance.
* @internal
*/
constructor() {
window.addEventListener('resize', () => {
Expand Down
11 changes: 11 additions & 0 deletions dist/features/mouse/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IFeature, IProxy, UpdateData } from '../../types';
/**
* Feature to enable mouse controls
* @hidden
*/
export declare class Mouse implements IFeature {
get name(): string;
init(proxy: IProxy): void;
destroy(): void;
update(data: UpdateData): void;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { writeCache } from '../../utils/cache';
/**
* Plugin to enable mouse controls
* Feature to enable mouse controls
* @hidden
*/
export class Mouse {
Expand Down
Loading

0 comments on commit f42862d

Please sign in to comment.