@ribajs/bs4
Advanced tools
Comparing version 1.8.0 to 1.9.0-alpha.0
@@ -16,7 +16,3 @@ module.exports = { | ||
"plugins": [ | ||
[ | ||
"@babel/plugin-transform-runtime", { | ||
"corejs": 3 | ||
} | ||
], | ||
"@babel/plugin-syntax-export-default-from", | ||
@@ -23,0 +19,0 @@ "@babel/plugin-proposal-class-properties", |
{ | ||
"name": "@ribajs/bs4", | ||
"description": "Bootstrap 4 module for Riba.js", | ||
"version": "1.8.0", | ||
"version": "1.9.0-alpha.0", | ||
"author": "Pascal Garber <pascal@artandcode.studio>", | ||
@@ -37,39 +37,42 @@ "contributors": [], | ||
"scripts": { | ||
"test": "npm run clean && npm run type-check && jest --config=jest.config.js", | ||
"type-check": "eslint src --ext .js,.jsx,.ts,.tsx --fix && tsc --noEmit", | ||
"build": "npm run type-check && npm run build:module", | ||
"test": "yarn run clean && yarn run lint && jest --config=jest.config.js", | ||
"lint": "eslint src --ext .js,.jsx,.ts,.tsx --fix && tsc --noEmit", | ||
"build": "npm run lint && npm run build:module", | ||
"build:module": "tsc", | ||
"clean": "rm -rf ./dist ./lib", | ||
"packages:link": "npm link @ribajs/core @ribajs/extras" | ||
"packages:npm:link": "npm link @ribajs/core @ribajs/extras" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.7.7", | ||
"@babel/core": "^7.7.7", | ||
"@babel/plugin-proposal-class-properties": "^7.7.4", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.7.7", | ||
"@babel/plugin-proposal-optional-chaining": "^7.7.5", | ||
"@babel/plugin-syntax-export-default-from": "^7.7.4", | ||
"@babel/plugin-transform-runtime": "^7.7.6", | ||
"@babel/preset-env": "^7.7.7", | ||
"@babel/preset-typescript": "^7.7.7", | ||
"@babel/runtime-corejs3": "^7.7.7", | ||
"@types/jest": "^24.0.25", | ||
"@typescript-eslint/eslint-plugin": "^2.15.0", | ||
"@typescript-eslint/parser": "^2.15.0", | ||
"babel-loader": "^8.0.6", | ||
"@babel/cli": "^7.8.4", | ||
"@babel/core": "^7.9.0", | ||
"@babel/plugin-proposal-class-properties": "^7.8.3", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.9.5", | ||
"@babel/plugin-proposal-optional-chaining": "^7.9.0", | ||
"@babel/plugin-syntax-export-default-from": "^7.8.3", | ||
"@babel/preset-env": "^7.9.5", | ||
"@babel/preset-typescript": "^7.9.0", | ||
"@babel/runtime-corejs3": "^7.9.2", | ||
"@ribajs/tsconfig": "1.9.0-alpha.0", | ||
"@ribajs/types": "1.8.3", | ||
"@types/jest": "^25.2.1", | ||
"@typescript-eslint/eslint-plugin": "^2.29.0", | ||
"@typescript-eslint/parser": "^2.29.0", | ||
"babel-loader": "^8.1.0", | ||
"babel-plugin-array-includes": "^2.0.3", | ||
"core-js": "^3.6.2", | ||
"core-js": "^3.6.5", | ||
"eslint": "^6.8.0", | ||
"jest": "^24.9.0", | ||
"jest-extended": "^0.11.2", | ||
"ts-jest": "^24.3.0", | ||
"typescript": "^3.7.4", | ||
"webpack": "^4.41.5", | ||
"webpack-cli": "^3.3.10" | ||
"jest": "^25.4.0", | ||
"jest-extended": "^0.11.5", | ||
"ts-jest": "^25.4.0", | ||
"typescript": "^3.8.3", | ||
"webpack": "^5.0.0-beta.15", | ||
"webpack-cli": "^3.3.11" | ||
}, | ||
"dependencies": { | ||
"@ribajs/core": "^1.8.0", | ||
"@ribajs/extras": "^1.8.0", | ||
"@ribajs/cache": "1.9.0-alpha.0", | ||
"@ribajs/core": "1.9.0-alpha.0", | ||
"@ribajs/extras": "1.9.0-alpha.0", | ||
"@ribajs/utils": "1.9.0-alpha.0", | ||
"bootstrap": "^4.4.1", | ||
"popper.js": "^1.16.0" | ||
"popper.js": "^1.16.1" | ||
}, | ||
@@ -79,2 +82,2 @@ "bugs": { | ||
} | ||
} | ||
} |
import { Binder, EventDispatcher } from '@ribajs/core'; | ||
import { CollapseService } from '../services/collapse.service'; | ||
import { Utils } from '../services/utils.service'; | ||
import { onRoute } from '@ribajs/utils/src/url'; | ||
@@ -13,7 +13,7 @@ /** | ||
routine(el: HTMLElement, url: string) { | ||
const collapseService = new CollapseService([this.el]); | ||
const collapseService = new CollapseService(this.el, [], {toggle: false}); | ||
const dispatcher = new EventDispatcher('main'); | ||
const checkURL = (urlToCheck?: string) => { | ||
if (urlToCheck && Utils.onRoute(urlToCheck)) { | ||
if (urlToCheck && onRoute(urlToCheck)) { | ||
collapseService.hide(); | ||
@@ -20,0 +20,0 @@ return true; |
import { Binder } from '@ribajs/core'; | ||
// import { CollapseService } from '../services/collapse.service'; | ||
import { CollapseService } from '../services/collapse.service'; | ||
/** | ||
* | ||
* @see https://getbootstrap.com/docs/4.1/components/collapse/ | ||
* @deprecated | ||
*/ | ||
export const collapseBinder: Binder<string> = { | ||
name: 'bs4-collapse', | ||
bind() { | ||
console.warn('bs4-collapse is deprecated, use bs4-toggle-collapse-on-click instead.'); | ||
}, | ||
routine(el: HTMLElement, targetSelector: string) { | ||
const targets = el.querySelectorAll<HTMLElement>(targetSelector); | ||
const targets = document.querySelectorAll<HTMLElement>(targetSelector); | ||
const collapseService = new CollapseService(targets); | ||
const collapseServices: CollapseService[] = []; | ||
const onStateChange = () => { | ||
if (collapseService.isCollapsed()) { | ||
el.classList.add(CollapseService.CLASSNAME.COLLAPSED); | ||
el.setAttribute('aria-expanded', 'false'); | ||
} else { | ||
el.classList.remove(CollapseService.CLASSNAME.COLLAPSED); | ||
el.setAttribute('aria-expanded', 'true'); | ||
} | ||
}; | ||
targets.forEach((target) => { | ||
target.addEventListener(CollapseService.EVENT.SHOWN, onStateChange.bind(this)); | ||
target.addEventListener(CollapseService.EVENT.HIDDEN, onStateChange.bind(this)); | ||
collapseServices.push(new CollapseService(target, [el], {toggle: false })); | ||
}); | ||
@@ -33,7 +25,7 @@ | ||
event.preventDefault(); | ||
collapseService.toggle(); | ||
collapseServices.forEach((collapseService) => { | ||
collapseService.toggle(); | ||
}); | ||
}); | ||
onStateChange(); | ||
}, | ||
}; |
import { Binder, EventDispatcher } from '@ribajs/core'; | ||
import { CollapseService } from '../services/collapse.service'; | ||
import { Utils } from '../services/utils.service'; | ||
import { onRoute } from '@ribajs/utils/src/url'; | ||
@@ -13,7 +13,7 @@ /** | ||
routine(el: HTMLElement, url: string) { | ||
const collapseService = new CollapseService([el]); | ||
const collapseService = new CollapseService(el, [], {toggle: false}); | ||
const dispatcher = new EventDispatcher('main'); | ||
const checkURL = (urlToCheck?: string) => { | ||
if (urlToCheck && Utils.onRoute(urlToCheck)) { | ||
if (urlToCheck && onRoute(urlToCheck)) { | ||
collapseService.show(); | ||
@@ -20,0 +20,0 @@ return true; |
@@ -1,2 +0,3 @@ | ||
import { Binder, Utils } from '@ribajs/core'; | ||
import { Binder } from '@ribajs/core'; | ||
import { debounce } from '@ribajs/utils/src/control'; | ||
@@ -56,3 +57,3 @@ /** | ||
}; | ||
window.addEventListener('scroll', Utils.debounce(this.customData.onScroll.bind(this)), { passive: true }); | ||
window.addEventListener('scroll', debounce(this.customData.onScroll.bind(this)), { passive: true }); | ||
this.customData.onScroll(); | ||
@@ -66,4 +67,4 @@ }, | ||
unbind() { | ||
window.removeEventListener('scroll', Utils.debounce(this.customData.onScroll.bind(this))); | ||
window.removeEventListener('scroll', debounce(this.customData.onScroll.bind(this))); | ||
}, | ||
}; |
export { collapseOnUrlBinder } from './bs4-collapse-on-url.binder'; | ||
export { collapseBinder } from './bs4-collapse.binder'; | ||
export { toggleCollapseOnEventBinder } from './bs4-toggle-collapse-on-event.binder'; | ||
export { dropdownBinder } from './bs4-dropdown.binder'; | ||
@@ -8,1 +9,3 @@ export { expanOnUrlBinder } from './bs4-expan-on-url.binder'; | ||
export { scrollToOnEventBinder } from './scroll-to-on-event.binder'; | ||
export { toggleAttributeBinder } from './toggle-attribute.binder'; | ||
export { toggleClassBinder } from './toggle-class.binder'; |
@@ -1,2 +0,3 @@ | ||
import { Binder, Utils } from '@ribajs/core'; | ||
import { Binder } from '@ribajs/core'; | ||
import { scrollTo } from '@ribajs/utils/src/dom'; | ||
@@ -10,3 +11,3 @@ export const scrollToOnEventBinder: Binder<string> = { | ||
const scrollElement = el.dataset.scrollElement ? document.querySelector(el.dataset.scrollElement) : window; | ||
Utils.scrollTo(this.customData.target, offset, scrollElement); | ||
scrollTo(this.customData.target, offset, scrollElement); | ||
event.preventDefault(); | ||
@@ -13,0 +14,0 @@ }; |
import { | ||
handleizeFormatter, | ||
} from '@ribajs/core'; | ||
import { CollapseService } from '../../services/collapse.service'; | ||
import { CollapseService, EVENT_HIDE, EVENT_SHOW } from '../../services/collapse.service'; | ||
@@ -47,3 +47,3 @@ import { TemplatesComponent } from '../templates/templates.component'; | ||
// protected collapseService?: CollapseService; | ||
// protected collapseServices: CollapseService[] = []; | ||
@@ -70,3 +70,3 @@ static get observedAttributes() { | ||
this.initItemEventListeners(item, target); | ||
CollapseService.hide(target); | ||
new CollapseService(target, [this.el], {toggle: false}).hide(); | ||
} | ||
@@ -77,9 +77,11 @@ } | ||
const target = this.el.querySelector<HTMLElement>(`[data-index="${index}"]`); | ||
const others = this.el.querySelectorAll<HTMLElement>(`[data-index]:not([data-index="${index}"])`); | ||
const others = Array.from(this.el.querySelectorAll<HTMLElement>(`[data-index]:not([data-index="${index}"])`)); | ||
if (others) { | ||
CollapseService.hideAll(others); | ||
for (const other of others) { | ||
new CollapseService(other, [], {toggle: false}).hide(); | ||
} | ||
} | ||
if (target) { | ||
this.initItemEventListeners(item, target); | ||
CollapseService.show(target); | ||
new CollapseService(target, [], {toggle: false}).show(); | ||
} | ||
@@ -90,9 +92,11 @@ } | ||
const target = this.el.querySelector<HTMLElement>(`[data-index="${index}"]`); | ||
const others = this.el.querySelectorAll<HTMLElement>(`[data-index]:not([data-index="${index}"])`); | ||
const others = Array.from(this.el.querySelectorAll<HTMLElement>(`[data-index]:not([data-index="${index}"])`)); | ||
if (others) { | ||
CollapseService.hideAll(others); | ||
for (const other of others) { | ||
new CollapseService(other, [], {toggle: false}).hide(); | ||
} | ||
} | ||
if (target) { | ||
this.initItemEventListeners(item, target); | ||
CollapseService.toggle(target); | ||
new CollapseService(target, [], {toggle: false}).toggle(); | ||
} | ||
@@ -102,11 +106,19 @@ } | ||
protected initItemEventListeners(item: AccordionItem, element: HTMLElement) { | ||
element.removeEventListener(CollapseService.EVENT.HIDE, this.onHide.bind(this, element, item)); | ||
element.removeEventListener(CollapseService.EVENT.SHOW, this.onShow.bind(this, element, item)); | ||
element.addEventListener(CollapseService.EVENT.HIDE, this.onHide.bind(this, element, item), { once: true }); | ||
element.addEventListener(CollapseService.EVENT.SHOW, this.onShow.bind(this, element, item), { once: true }); | ||
element.removeEventListener(EVENT_HIDE, this.onHide.bind(this, element, item)); | ||
element.removeEventListener(EVENT_SHOW, this.onShow.bind(this, element, item)); | ||
element.addEventListener(EVENT_HIDE, this.onHide.bind(this, element, item), { once: true }); | ||
element.addEventListener(EVENT_SHOW, this.onShow.bind(this, element, item), { once: true }); | ||
} | ||
protected getContentChildByIndex() { | ||
return this.el.querySelector(`.card-body > *`) || undefined; | ||
} | ||
protected onShow(element: HTMLElement, item: AccordionItem) { | ||
item.show = true; | ||
item.iconDirection = 'up'; | ||
const firstContentChild = this.getContentChildByIndex(); | ||
if (firstContentChild) { | ||
this.triggerVisibilityChangedForElement(firstContentChild, item.show); | ||
} | ||
} | ||
@@ -117,2 +129,6 @@ | ||
item.iconDirection = 'down'; | ||
const firstContentChild = this.getContentChildByIndex(); | ||
if (firstContentChild) { | ||
this.triggerVisibilityChangedForElement(firstContentChild, item.show); | ||
} | ||
} | ||
@@ -128,2 +144,15 @@ | ||
/** | ||
* Trigger `visibility-changed` for components that need to update if visibility changes. | ||
* Se also bsf-tabs | ||
* @param element | ||
* @param visibile | ||
*/ | ||
protected triggerVisibilityChangedForElement(element: Element, visibile: boolean) { | ||
setTimeout(() => { | ||
// Use this event to update any custom element when it becomes visibile | ||
element.dispatchEvent(new CustomEvent('visibility-changed', {detail: {visibile}})); | ||
}, 200); | ||
} | ||
protected connectedCallback() { | ||
@@ -146,3 +175,3 @@ super.connectedCallback(); | ||
protected async afterBind() { | ||
return await super.beforeBind(); | ||
return await super.afterBind(); | ||
} | ||
@@ -149,0 +178,0 @@ |
@@ -1,3 +0,3 @@ | ||
import { Component, EventDispatcher, Binder } from '@ribajs/core'; | ||
import { CollapseService } from '../../services/collapse.service'; | ||
import { Component, EventDispatcher } from '@ribajs/core'; | ||
import { CollapseService, EVENT_SHOWN, EVENT_HIDDEN, CLASS_NAME_COLLAPSED } from '../../services/collapse.service'; | ||
@@ -13,12 +13,11 @@ export class Bs4NavbarComponent extends Component { | ||
isCollapsed: true, | ||
collapseSelector: '.navbar-collapse', | ||
animated: true, | ||
collapseSelector: '.navbar-collapse' | ||
}; | ||
protected collapse?: NodeListOf<HTMLElement>; | ||
protected collapseService?: CollapseService; | ||
protected collapseElements: NodeListOf<HTMLElement> | HTMLElement[] = []; | ||
protected collapseServices: CollapseService[] = []; | ||
protected router?: EventDispatcher; | ||
static get observedAttributes() { | ||
return ['collapse-selector', 'animated']; | ||
return ['collapse-selector']; | ||
} | ||
@@ -30,6 +29,14 @@ | ||
public toggle(context?: Binder<any>, event?: Event) { | ||
if (this.collapseService) { | ||
this.collapseService.toggle(this.scope.animated); | ||
protected async afterBind() { | ||
await super.afterBind(); | ||
this.hide(); | ||
} | ||
public toggle(event?: Event) { | ||
for (const collapseService of this.collapseServices) { | ||
collapseService.toggle(); | ||
} | ||
if (event) { | ||
@@ -41,5 +48,5 @@ event.preventDefault(); | ||
public show(context?: Binder<any>, event?: Event) { | ||
if (this.collapseService) { | ||
this.collapseService.show(this.scope.animated); | ||
public show(event?: Event) { | ||
for (const collapseService of this.collapseServices) { | ||
collapseService.show(); | ||
} | ||
@@ -52,5 +59,5 @@ if (event) { | ||
public hide(context?: Binder<any>, event?: Event) { | ||
if (this.collapseService) { | ||
this.collapseService.hide(this.scope.animated); | ||
public hide(event?: Event) { | ||
for (const collapseService of this.collapseServices) { | ||
collapseService.hide(); | ||
} | ||
@@ -79,3 +86,3 @@ if (event) { | ||
this.collapse = this.el.querySelectorAll(this.scope.collapseSelector) || undefined; | ||
this.collapseElements = this.el.querySelectorAll<HTMLElement>(this.scope.collapseSelector) || []; | ||
@@ -85,12 +92,17 @@ // Add new event listeners | ||
if (this.collapse) { | ||
this.collapseService = new CollapseService(this.collapse); | ||
if (this.collapseElements) { | ||
for (const collapseElement of Array.from(this.collapseElements)) { | ||
this.collapseServices.push(new CollapseService(collapseElement, [this.el], {toggle: false})); | ||
} | ||
} | ||
this.hide(); | ||
} | ||
protected addCollapseEventListeners() { | ||
if (this.collapse) { | ||
this.collapse.forEach((collapse) => { | ||
collapse.addEventListener(CollapseService.EVENT.SHOWN, this.onStateChange.bind(this)); | ||
collapse.addEventListener(CollapseService.EVENT.HIDDEN, this.onStateChange.bind(this)); | ||
if (this.collapseElements) { | ||
this.collapseElements.forEach((collapseElement: HTMLElement) => { | ||
collapseElement.addEventListener(EVENT_SHOWN, this.onStateChange.bind(this)); | ||
collapseElement.addEventListener(EVENT_HIDDEN, this.onStateChange.bind(this)); | ||
}); | ||
@@ -101,6 +113,6 @@ } | ||
protected removeCollapseEventListeners() { | ||
if (this.collapse) { | ||
this.collapse.forEach((collapse) => { | ||
collapse.removeEventListener(CollapseService.EVENT.SHOWN, this.onStateChange.bind(this)); | ||
collapse.removeEventListener(CollapseService.EVENT.HIDDEN, this.onStateChange.bind(this)); | ||
if (this.collapseElements) { | ||
this.collapseElements.forEach((collapseElement: HTMLElement) => { | ||
collapseElement.removeEventListener(EVENT_SHOWN, this.onStateChange.bind(this)); | ||
collapseElement.removeEventListener(EVENT_HIDDEN, this.onStateChange.bind(this)); | ||
}); | ||
@@ -120,11 +132,9 @@ } | ||
if (this.collapseService) { | ||
this.scope.isCollapsed = this.collapseService.isCollapsed(); | ||
} | ||
this.scope.isCollapsed = !!this.collapseServices[0]?.isCollapsed(); | ||
if (this.scope.isCollapsed) { | ||
this.el.classList.add(CollapseService.CLASSNAME.COLLAPSED); | ||
this.el.classList.add(CLASS_NAME_COLLAPSED); | ||
this.el.setAttribute('aria-expanded', 'false'); | ||
} else { | ||
this.el.classList.remove(CollapseService.CLASSNAME.COLLAPSED); | ||
this.el.classList.remove(CLASS_NAME_COLLAPSED); | ||
this.el.setAttribute('aria-expanded', 'true'); | ||
@@ -135,5 +145,3 @@ } | ||
protected onNewPageReady() { | ||
if (this.collapseService) { | ||
this.collapseService.hide(this.scope.animated); | ||
} | ||
this.hide(); | ||
} | ||
@@ -140,0 +148,0 @@ |
import { | ||
Component, | ||
EventDispatcher, | ||
Utils, | ||
} from '@ribajs/core'; | ||
import { getViewportDimensions } from '@ribajs/utils/src/dom'; | ||
@@ -140,3 +140,3 @@ type State = 'overlay-left' | 'overlay-right' | 'side-left' | 'side-right' | 'hidden'; | ||
public show() { | ||
const vw = Utils.getViewportDimensions().w; | ||
const vw = getViewportDimensions().w; | ||
if (vw < this.scope.overlayOnSlimmerThan) { | ||
@@ -237,3 +237,3 @@ this.scope.state = 'overlay-' + this.scope.position as State; | ||
} | ||
const vw = Utils.getViewportDimensions().w; | ||
const vw = getViewportDimensions().w; | ||
if (this.scope.autoHideOnSlimmerThan > -1 && vw < this.scope.autoHideOnSlimmerThan) { | ||
@@ -240,0 +240,0 @@ return this.hide(); |
import { TemplatesComponent } from '../templates/templates.component'; | ||
import { Utils } from '@ribajs/core'; | ||
import { clone, camelCase } from '@ribajs/utils/src/type'; | ||
@@ -19,2 +19,6 @@ import { Dragscroll, DragscrollOptions, Autoscroll, AutoscrollOptions, Utils as ExtraUtils, ScrollPosition, ScrollEventsService } from '@ribajs/extras'; | ||
export type ControlsPosition = 'insite-middle' | 'insite-bottom' | 'insite-top' | 'outsite-middle' | 'outsite-bottom' | 'outsite-top'; | ||
export type IndicatorsPosition = 'insite-bottom' | 'insite-top' | 'insite-right' | 'insite-left' | 'outsite-bottom' | 'outsite-top' | 'outsite-right' | 'outsite-left'; | ||
export interface Position extends DOMRect { | ||
@@ -41,6 +45,16 @@ centerX: number; | ||
export interface Options { | ||
/** Show controls */ | ||
controls: boolean; | ||
/** Position of the controls */ | ||
controlsPosition: ControlsPosition; | ||
/** Show indicators */ | ||
indicators: boolean; | ||
/** Position of the indicators */ | ||
indicatorsPosition: IndicatorsPosition; | ||
/** Pauses autoscolling on hover or focus */ | ||
pauseOnHover: boolean; | ||
/** number of slides to be scrolled by clicking on the controls */ | ||
slidesToScroll: number; | ||
/** Show controls */ | ||
controls: boolean; | ||
/** Autoscroll to the nearest slide after manual scroll or dragscroll */ | ||
sticky: boolean; | ||
/** Slides are dragable on desktop browsers */ | ||
@@ -64,8 +78,2 @@ draggable: boolean; | ||
angle: 'vertical' | 'horizontal'; | ||
/** Pauses autoscolling on hover or focus */ | ||
pauseOnHover: boolean; | ||
/** Autoscroll to the nearest slide after manual scroll or dragscroll */ | ||
sticky: boolean; | ||
/** Show indicators */ | ||
indicators: boolean; | ||
/** Pause on autoplay (with interval) */ | ||
@@ -86,2 +94,4 @@ pause: boolean; | ||
goTo: Bs4SlideshowComponent['goTo']; | ||
controlsPositionClass: string; | ||
indicatorsPositionClass: string; | ||
items: Slide[]; | ||
@@ -132,2 +142,3 @@ } | ||
'controls', | ||
'controls-position', | ||
'draggable', | ||
@@ -146,2 +157,3 @@ 'autoplay', | ||
'indicators', | ||
'indicators-position', | ||
'pause', | ||
@@ -153,2 +165,3 @@ | ||
'sm-controls', | ||
'sm-controls-position', | ||
'sm-draggable', | ||
@@ -167,2 +180,3 @@ 'sm-autoplay', | ||
'sm-indicators', | ||
'sm-indicators-position', | ||
'sm-pause', | ||
@@ -174,2 +188,3 @@ | ||
'md-controls', | ||
'md-controls-position', | ||
'md-draggable', | ||
@@ -188,2 +203,3 @@ 'md-autoplay', | ||
'md-indicators', | ||
'sm-indicators-position', | ||
'md-pause', | ||
@@ -195,2 +211,3 @@ | ||
'lg-controls', | ||
'lg-controls-position', | ||
'lg-draggable', | ||
@@ -209,2 +226,3 @@ 'lg-autoplay', | ||
'lg-indicators', | ||
'lg-indicators-position', | ||
'lg-pause', | ||
@@ -216,2 +234,3 @@ | ||
'xl-controls', | ||
'xl-controls-position', | ||
'xl-draggable', | ||
@@ -230,2 +249,3 @@ 'xl-autoplay', | ||
'xl-indicators', | ||
'xl-indicators-position', | ||
'xl-pause', | ||
@@ -303,2 +323,8 @@ ]; | ||
controls: true, | ||
controlsPosition: 'insite-middle', | ||
pauseOnHover: true, | ||
sticky: false, | ||
indicators: true, | ||
indicatorsPosition: 'insite-bottom', | ||
pause: false, | ||
draggable: true, | ||
@@ -313,6 +339,2 @@ autoplay: false, | ||
angle: 'horizontal', | ||
pauseOnHover: true, | ||
sticky: false, | ||
indicators: true, | ||
pause: false, | ||
@@ -335,2 +357,6 @@ // Responsive options | ||
}, | ||
// Classes | ||
controlsPositionClass: '', | ||
indicatorsPositionClass: '', | ||
}; | ||
@@ -365,2 +391,7 @@ | ||
if (!this.scope.items[index]) { | ||
console.error(`Slide with index "${index}" not found!`, this.scope.items[index]); | ||
return; | ||
} | ||
if (this.scope.angle === 'vertical') { | ||
@@ -402,17 +433,19 @@ // Check if we do not need to slide | ||
protected setOptions(dest: ResponsiveOptions | Options, source: ResponsiveOptions | Options) { | ||
dest.slidesToScroll = typeof(source.slidesToScroll) !== 'undefined' ? Utils.clone(false, source.slidesToScroll) : dest.slidesToScroll; | ||
dest.controls = typeof(source.controls) !== 'undefined' ? Utils.clone(false, source.controls) : dest.controls; | ||
dest.draggable = typeof(source.draggable) !== 'undefined' ? Utils.clone(false, source.draggable) : dest.draggable; | ||
dest.autoplay = typeof(source.autoplay) !== 'undefined' ? Utils.clone(false, source.autoplay) : dest.autoplay; | ||
dest.autoplayInterval = typeof(source.autoplayInterval) !== 'undefined' ? Utils.clone(false, source.autoplayInterval) : dest.autoplayInterval; | ||
dest.autoplayVelocity = typeof(source.autoplayVelocity) !== 'undefined' ? Utils.clone(false, source.autoplayVelocity) : dest.autoplayVelocity; | ||
dest.controlPrevIconSrc = typeof(source.controlPrevIconSrc) !== 'undefined' ? Utils.clone(false, source.controlPrevIconSrc) : dest.controlPrevIconSrc; | ||
dest.controlNextIconSrc = typeof(source.controlNextIconSrc) !== 'undefined' ? Utils.clone(false, source.controlNextIconSrc) : dest.controlNextIconSrc; | ||
dest.indicatorActiveIconSrc = typeof(source.indicatorActiveIconSrc) !== 'undefined' ? Utils.clone(false, source.indicatorActiveIconSrc) : dest.indicatorActiveIconSrc; | ||
dest.indicatorInactiveIconSrc = typeof(source.indicatorInactiveIconSrc) !== 'undefined' ? Utils.clone(false, source.indicatorInactiveIconSrc) : dest.indicatorInactiveIconSrc; | ||
dest.angle = typeof(source.angle) !== 'undefined' ? Utils.clone(false, source.angle) : dest.angle; | ||
dest.pauseOnHover = typeof(source.pauseOnHover) !== 'undefined' ? Utils.clone(false, source.pauseOnHover) : dest.pauseOnHover; | ||
dest.sticky = typeof(source.sticky) !== 'undefined' ? Utils.clone(false, source.sticky) : dest.sticky; | ||
dest.indicators = typeof(source.indicators) !== 'undefined' ? Utils.clone(false, source.indicators) : dest.indicators; | ||
dest.pause = typeof(source.pause) !== 'undefined' ? Utils.clone(false, source.pause) : dest.pause; | ||
dest.slidesToScroll = typeof(source.slidesToScroll) !== 'undefined' ? clone(false, source.slidesToScroll) : dest.slidesToScroll; | ||
dest.controls = typeof(source.controls) !== 'undefined' ? clone(false, source.controls) : dest.controls; | ||
dest.controlsPosition = typeof(source.controlsPosition) !== 'undefined' ? clone(false, source.controlsPosition) : dest.controlsPosition; | ||
dest.draggable = typeof(source.draggable) !== 'undefined' ? clone(false, source.draggable) : dest.draggable; | ||
dest.autoplay = typeof(source.autoplay) !== 'undefined' ? clone(false, source.autoplay) : dest.autoplay; | ||
dest.autoplayInterval = typeof(source.autoplayInterval) !== 'undefined' ? clone(false, source.autoplayInterval) : dest.autoplayInterval; | ||
dest.autoplayVelocity = typeof(source.autoplayVelocity) !== 'undefined' ? clone(false, source.autoplayVelocity) : dest.autoplayVelocity; | ||
dest.controlPrevIconSrc = typeof(source.controlPrevIconSrc) !== 'undefined' ? clone(false, source.controlPrevIconSrc) : dest.controlPrevIconSrc; | ||
dest.controlNextIconSrc = typeof(source.controlNextIconSrc) !== 'undefined' ? clone(false, source.controlNextIconSrc) : dest.controlNextIconSrc; | ||
dest.indicatorActiveIconSrc = typeof(source.indicatorActiveIconSrc) !== 'undefined' ? clone(false, source.indicatorActiveIconSrc) : dest.indicatorActiveIconSrc; | ||
dest.indicatorInactiveIconSrc = typeof(source.indicatorInactiveIconSrc) !== 'undefined' ? clone(false, source.indicatorInactiveIconSrc) : dest.indicatorInactiveIconSrc; | ||
dest.angle = typeof(source.angle) !== 'undefined' ? clone(false, source.angle) : dest.angle; | ||
dest.pauseOnHover = typeof(source.pauseOnHover) !== 'undefined' ? clone(false, source.pauseOnHover) : dest.pauseOnHover; | ||
dest.sticky = typeof(source.sticky) !== 'undefined' ? clone(false, source.sticky) : dest.sticky; | ||
dest.indicators = typeof(source.indicators) !== 'undefined' ? clone(false, source.indicators) : dest.indicators; | ||
dest.indicatorsPosition = typeof(source.indicatorsPosition) !== 'undefined' ? clone(false, source.indicatorsPosition) : dest.indicatorsPosition; | ||
dest.pause = typeof(source.pause) !== 'undefined' ? clone(false, source.pause) : dest.pause; | ||
} | ||
@@ -423,2 +456,3 @@ | ||
dest.controls = typeof(dest.controls) === 'undefined' ? source.controls : dest.controls; | ||
dest.controlsPosition = typeof(dest.controlsPosition) === 'undefined' ? source.controlsPosition : dest.controlsPosition; | ||
dest.draggable = typeof(dest.draggable) === 'undefined' ? source.draggable : dest.draggable; | ||
@@ -436,2 +470,3 @@ dest.autoplay = typeof(dest.autoplay) === 'undefined' ? source.autoplay : dest.autoplay; | ||
dest.indicators = typeof(dest.indicators) === 'undefined' ? source.indicators : dest.indicators; | ||
dest.indicatorsPosition = typeof(dest.indicatorsPosition) === 'undefined' ? source.indicatorsPosition : dest.indicatorsPosition; | ||
dest.pause = typeof(dest.pause) === 'undefined' ? source.pause : dest.pause; | ||
@@ -450,2 +485,24 @@ } | ||
protected setControlsOptions() { | ||
const xsControlsPosition = this.scope.xs.controlsPosition?.split('-') as ControlsPosition[]; | ||
const smControlsPosition = this.scope.sm.controlsPosition?.split('-') as ControlsPosition[]; | ||
const mdControlsPosition = this.scope.md.controlsPosition?.split('-') as ControlsPosition[]; | ||
const lgControlsPosition = this.scope.lg.controlsPosition?.split('-') as ControlsPosition[]; | ||
const xlControlsPosition = this.scope.xl.controlsPosition?.split('-') as ControlsPosition[]; | ||
this.scope.controlsPositionClass = `control-${xsControlsPosition[0]} control-${xsControlsPosition[1]} control-sm-${smControlsPosition[0]} control-sm-${smControlsPosition[1]} control-md-${mdControlsPosition[0]} control-md-${mdControlsPosition[1]} control-lg-${lgControlsPosition[0]} control-lg-${lgControlsPosition[1]} control-xl-${xlControlsPosition[0]} control-xl-${xlControlsPosition[1]}`; | ||
} | ||
protected setIndicatorsOptions() { | ||
const xsIndicatorsPosition = this.scope.xs.indicatorsPosition?.split('-') as IndicatorsPosition[]; | ||
const smIndicatorsPosition = this.scope.sm.indicatorsPosition?.split('-') as IndicatorsPosition[]; | ||
const mdIndicatorsPosition = this.scope.md.indicatorsPosition?.split('-') as IndicatorsPosition[]; | ||
const lgIndicatorsPosition = this.scope.lg.indicatorsPosition?.split('-') as IndicatorsPosition[]; | ||
const xlIndicatorsPosition = this.scope.xl.indicatorsPosition?.split('-') as IndicatorsPosition[]; | ||
this.scope.indicatorsPositionClass = `indicators-${xsIndicatorsPosition[0]} indicators-${xsIndicatorsPosition[1]} indicators-sm-${smIndicatorsPosition[0]} indicators-sm-${smIndicatorsPosition[1]} indicators-md-${mdIndicatorsPosition[0]} indicators-md-${mdIndicatorsPosition[1]} indicators-lg-${lgIndicatorsPosition[0]} indicators-lg-${lgIndicatorsPosition[1]} indicators-xl-${xlIndicatorsPosition[0]} indicators-xl-${xlIndicatorsPosition[1]}`; | ||
} | ||
// TODO create independent bs4 breakpoint service | ||
@@ -486,2 +543,4 @@ protected getBreakpoint(): Breakpoint { | ||
} | ||
this.setControlsOptions(); | ||
this.setIndicatorsOptions(); | ||
} | ||
@@ -499,2 +558,7 @@ | ||
} | ||
this.setSlidePositions(); | ||
const index = this.setCenteredSlideActive(); | ||
if (this.scope.sticky) { | ||
this.goTo(index); | ||
} | ||
} | ||
@@ -656,3 +720,3 @@ | ||
const intervalsTimeMs = this.scope.autoplayVelocity * 10000; | ||
console.debug('intervalsTimeMs', intervalsTimeMs); | ||
// console.debug('intervalsTimeMs', intervalsTimeMs); | ||
this.continuousAutoplayIntervalIndex = window.setInterval(this.onScrollend.bind(this), intervalsTimeMs); | ||
@@ -817,7 +881,7 @@ } | ||
protected setCenteredSlideActive() { | ||
protected setCenteredSlideActive(): number { | ||
const index = this.getMostCenteredSlideIndex(); | ||
this.setAllSlidesUnactive(index); | ||
if (!this.scope.items[index]) { | ||
return; | ||
return -1; | ||
} | ||
@@ -828,2 +892,3 @@ this.scope.items[index].active = true; | ||
} | ||
return index; | ||
} | ||
@@ -866,13 +931,5 @@ | ||
if (prevIndex < 0) { | ||
prevIndex = (this.slideElements.length - 1) - prevIndex; | ||
prevIndex = (this.slideElements.length - 1) + (prevIndex + 1); | ||
} | ||
// if (!this.isScrollableToIndex(prevIndex)) { | ||
// prevIndex--; | ||
// } | ||
// if (prevIndex < 0) { | ||
// prevIndex = (this.slideElements.length - 1) - prevIndex; | ||
// } | ||
return this.goTo(prevIndex); | ||
@@ -962,3 +1019,3 @@ } | ||
const parsedAttributeName = Utils.camelCase(attributeName); | ||
const parsedAttributeName = camelCase(attributeName); | ||
@@ -965,0 +1022,0 @@ |
@@ -0,1 +1,10 @@ | ||
/** | ||
* This components is used to trigger a toggle event used in other components or parts of your project. This site itself uses the bs4-toggle-button to open or close the sidebar. | ||
* @attribute "target-id" (Required) The id with which the toggle event is triggered | ||
* @method toggle Triggeres the toggle event | ||
* @property state Can be 'hidden' or something else | ||
* @property isClosed Is true if the state is 'hidden' | ||
* @property targetId Passed attribute value, see `target-id` attribute | ||
*/ | ||
import { | ||
@@ -6,4 +15,8 @@ Component, | ||
type State = 'undefined' | 'overlay-left' | 'overlay-right' | 'side-left' | 'side-right' | 'hidden'; | ||
import { | ||
TOGGLE_BUTTON, | ||
} from '../../constants'; | ||
type State = 'undefined' | 'overlay-left' | 'overlay-right' | 'side-left' | 'side-right' | 'hidden' | 'added' | 'removed'; | ||
interface Scope { | ||
@@ -13,2 +26,4 @@ targetId?: string; | ||
state: State; | ||
isActive: boolean; | ||
// depricated, use !isActive instead | ||
isClosed: boolean; | ||
@@ -24,2 +39,6 @@ } | ||
protected requiredAttributes() { | ||
return ['targetId']; | ||
} | ||
public static tagName = 'bs4-toggle-button'; | ||
@@ -35,2 +54,3 @@ | ||
state: 'undefined', | ||
isActive: true, | ||
isClosed: false, | ||
@@ -44,4 +64,5 @@ }; | ||
public toggle() { | ||
// console.debug('toggle', this.eventDispatcher); | ||
if (this.eventDispatcher) { | ||
this.eventDispatcher.trigger('toggle', this.scope.targetId); | ||
this.eventDispatcher.trigger(TOGGLE_BUTTON.eventNames.toggle, this.scope.targetId); | ||
} | ||
@@ -53,3 +74,3 @@ } | ||
// Trigger init to trigger there current state of all the components that are connected to this component | ||
return this.eventDispatcher?.trigger('init', this.scope.targetId); | ||
return this.eventDispatcher?.trigger(TOGGLE_BUTTON.eventNames.init, this.scope.targetId); | ||
} | ||
@@ -64,3 +85,4 @@ | ||
this.scope.state = state; | ||
this.scope.isClosed = state === 'hidden'; | ||
this.scope.isActive = state !== 'hidden' && state !== 'removed'; | ||
this.scope.isClosed = !this.scope.isActive; | ||
} | ||
@@ -70,14 +92,10 @@ | ||
if (this.eventDispatcher) { | ||
this.eventDispatcher.off('toggled', this.onToggledEvent); | ||
this.eventDispatcher.off(TOGGLE_BUTTON.eventNames.toggled, this.onToggledEvent); | ||
} | ||
this.eventDispatcher = new EventDispatcher('bs4-toggle-button:' + id); | ||
this.eventDispatcher.on('toggled', this.onToggledEvent.bind(this)); | ||
this.eventDispatcher = new EventDispatcher(TOGGLE_BUTTON.nsPrefix + id); | ||
this.eventDispatcher.on(TOGGLE_BUTTON.eventNames.toggled, this.onToggledEvent.bind(this)); | ||
// Triggered state triggered by `..trigger('init', ...` | ||
this.eventDispatcher.on('state', this.onToggledEvent.bind(this)); | ||
this.eventDispatcher.on(TOGGLE_BUTTON.eventNames.state, this.onToggledEvent.bind(this)); | ||
} | ||
protected requiredAttributes() { | ||
return ['targetId']; | ||
} | ||
protected attributeChangedCallback(attributeName: string, oldValue: any, newValue: any, namespace: string | null) { | ||
@@ -98,3 +116,3 @@ super.attributeChangedCallback(attributeName, oldValue, newValue, namespace); | ||
if (this.eventDispatcher) { | ||
this.eventDispatcher.off('toggled', this.onToggledEvent); | ||
this.eventDispatcher.off(TOGGLE_BUTTON.eventNames.toggled, this.onToggledEvent); | ||
} | ||
@@ -101,0 +119,0 @@ } |
@@ -1,5 +0,9 @@ | ||
export { Bs4DropdownComponent } from './bd4-dropdown/bs4-dropdown.component'; | ||
export { Bs4DropdownComponent } from './bs4-dropdown/bs4-dropdown.component'; | ||
export { Bs4AccordionComponent } from './bs4-accordion/bs4-accordion.component'; | ||
export { Bs4ButtonComponent } from './bs4-button/bs4-button.component'; | ||
export { Bs4CarouselComponent } from './bs4-carousel/bs4-carousel.component'; | ||
export { Bs4ContentsComponent } from './bs4-contents/bs4-contents.component'; | ||
export { Bs4IconComponent } from './bs4-icon/bs4-icon.component'; | ||
export { Bs4ScrollspyComponent } from './bs4-scrollspy/bs4-scrollspy.component'; | ||
export { Bs4ShareComponent } from './bs4-share/bs4-share.component'; | ||
export { Bs4SidebarComponent } from './bs4-sidebar/bs4-sidebar.component'; | ||
@@ -10,3 +14,3 @@ export { Bs4SlideshowComponent } from './bs4-slideshow/bs4-slideshow.component'; | ||
export { Bs4TabsComponent } from './bs4-tabs/bs4-tabs.component'; | ||
export { Bs4ButtonComponent } from './bs4-button/bs4-button.component'; | ||
export { Bs4AccordionComponent } from './bs4-accordion/bs4-accordion.component'; | ||
import { | ||
Component, | ||
Utils, | ||
} from '@ribajs/core'; | ||
import { | ||
camelCase, | ||
} from '@ribajs/utils/src/type'; | ||
export type AttributeType = string; // 'string' | 'number' | 'boolean'; | ||
@@ -77,3 +80,3 @@ | ||
} | ||
attributes[Utils.camelCase(attribute.name)] = attrValue; | ||
attributes[camelCase(attribute.name)] = attrValue; | ||
} | ||
@@ -80,0 +83,0 @@ return this.transformTemplateAttributes(attributes, index); |
@@ -7,6 +7,3 @@ export * from './services'; | ||
// export * from './interfaces/interfaces'; | ||
import bs4Module from './bs4.module'; | ||
export { bs4Module }; | ||
export default bs4Module; | ||
export * from './constants'; | ||
export * from './bs4.module'; |
@@ -0,147 +1,425 @@ | ||
/** | ||
* -------------------------------------------------------------------------- | ||
* Bootstrap (v4.3.1): collapse.js | ||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | ||
* -------------------------------------------------------------------------- | ||
*/ | ||
import { | ||
TRANSITION_END, | ||
Utils, | ||
} from './utils.service' | ||
import EventHandler from './dom/event-handler' | ||
import SelectorEngine from './dom/selector-engine' | ||
import Data from './dom/data' | ||
export interface Config { | ||
toggle: boolean; | ||
parent: string | HTMLElement; | ||
} | ||
/** | ||
* | ||
* @see https://github.com/twbs/bootstrap/blob/v4-dev/js/src/collapse.js | ||
* ------------------------------------------------------------------------ | ||
* Constants | ||
* ------------------------------------------------------------------------ | ||
*/ | ||
export const NAME = 'collapse' | ||
export const VERSION = '4.3.1' | ||
export const DATA_KEY = 'bs.collapse' | ||
export const EVENT_KEY = `.${DATA_KEY}` | ||
export const Default = { | ||
toggle: true, | ||
parent: '' | ||
} | ||
export const DefaultType = { | ||
toggle: 'boolean', | ||
parent: '(string|element)' | ||
} | ||
export const EVENT_SHOW = `show${EVENT_KEY}` | ||
export const EVENT_SHOWN = `shown${EVENT_KEY}` | ||
export const EVENT_HIDE = `hide${EVENT_KEY}` | ||
export const EVENT_HIDDEN = `hidden${EVENT_KEY}` | ||
export const CLASS_NAME_SHOW = 'show' | ||
export const CLASS_NAME_COLLAPSE = 'collapse' | ||
export const CLASS_NAME_COLLAPSING = 'collapsing' | ||
export const CLASS_NAME_COLLAPSED = 'collapsed' | ||
export const WIDTH = 'width' | ||
export const HEIGHT = 'height' | ||
export const SELECTOR_ACTIVES = '.show, .collapsing' | ||
// export const SELECTOR_DATA_TOGGLE = '[data-toggle="collapse"]' | ||
/** | ||
* ------------------------------------------------------------------------ | ||
* Class Definition | ||
* ------------------------------------------------------------------------ | ||
*/ | ||
export class CollapseService { | ||
_isTransitioning: boolean; | ||
_element: HTMLElement | null = null; | ||
_config: any; | ||
_triggerArray: HTMLElement[] | null = null; | ||
_selector: string | null = null; | ||
_parent: HTMLElement | null = null; | ||
public static DATA_KEY = 'bs.collapse'; | ||
public static EVENT_KEY = `.${CollapseService.DATA_KEY}`; | ||
public static DATA_API_KEY = '.data-api'; | ||
constructor(element: HTMLElement, triggerList: NodeListOf<HTMLElement> | HTMLElement[], config: Partial<Config> = {}) { | ||
this._isTransitioning = false | ||
this._element = element | ||
this._config = this._getConfig(config) | ||
this._triggerArray = Array.from(triggerList); | ||
// this._triggerArray = Array.from(SelectorEngine.find( | ||
// `${SELECTOR_DATA_TOGGLE}[href="#${element.id}"],` + | ||
// `${SELECTOR_DATA_TOGGLE}[data-target="#${element.id}"]` | ||
// )) as HTMLElement[]; | ||
public static EVENT = { | ||
SHOW : `show${CollapseService.EVENT_KEY}`, | ||
SHOWN : `shown${CollapseService.EVENT_KEY}`, | ||
HIDE : `hide${CollapseService.EVENT_KEY}`, | ||
HIDDEN : `hidden${CollapseService.EVENT_KEY}`, | ||
CLICK_DATA_API : `click${CollapseService.EVENT_KEY}${CollapseService.DATA_API_KEY}`, | ||
}; | ||
// const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE) as NodeListOf<HTMLElement>; | ||
public static CLASSNAME = { | ||
SHOW : 'show', | ||
COLLAPSE : 'collapse', // hidden | ||
COLLAPSING : 'collapsing', // animation | ||
COLLAPSED : 'collapsed', // Button / trigger element class if collapse element is collapsed | ||
}; | ||
// for (let i = 0, len = toggleList.length; i < len; i++) { | ||
// const elem = toggleList[i] | ||
// const selector = Utils.getSelectorFromElement(elem) | ||
// const filterElement = !selector ? [] : Array.from(SelectorEngine.find(selector)) | ||
// .filter(foundElem => foundElem === element) | ||
public static show(element: HTMLElement, animated = true) { | ||
element.dispatchEvent(new Event(CollapseService.EVENT.SHOW)); | ||
if (animated) { | ||
element.addEventListener('webkitTransitionEnd' as 'animationend', this.onShowTransitionEnd.bind(this, element), { once: true }); | ||
element.addEventListener('transitionend', this.onShowTransitionEnd.bind(this, element), { once: true }); | ||
element.classList.add(CollapseService.CLASSNAME.COLLAPSING); | ||
element.classList.remove(CollapseService.CLASSNAME.COLLAPSE); | ||
// Get and set height to start transition | ||
setTimeout(() => { | ||
// const duration = Utils.getTransitionDurationFromElement(element); | ||
if (element.firstElementChild) { | ||
const dimension = element.firstElementChild.getBoundingClientRect(); | ||
element.style.height = dimension.height + 'px'; | ||
} else { | ||
element.style.height = 'auto'; | ||
} | ||
}); | ||
} else { | ||
this.onShowTransitionEnd(element); | ||
// if (selector !== null && filterElement.length) { | ||
// this._selector = selector | ||
// // this._triggerArray.push(elem) | ||
// } | ||
// } | ||
this._parent = this._config.parent ? this._getParent() : null | ||
if (!this._config.parent) { | ||
this._addAriaAndCollapsedClass(this._element, this._triggerArray) | ||
// this._addAriaAndCollapsedClass(this._element, []) | ||
} | ||
} | ||
public static hide(element: HTMLElement, animated = true) { | ||
element.dispatchEvent(new Event(CollapseService.EVENT.HIDE)); | ||
if (animated) { | ||
element.addEventListener('webkitTransitionEnd' as 'animationend', this.onHideTransitionEnd.bind(this, element), { once: true }); | ||
element.addEventListener('transitionend', this.onHideTransitionEnd.bind(this, element), { once: true }); | ||
element.style.height = element.getBoundingClientRect().height + 'px' ; | ||
setTimeout(() => { | ||
element.classList.add(CollapseService.CLASSNAME.COLLAPSING); | ||
element.classList.remove(CollapseService.CLASSNAME.COLLAPSE); | ||
element.classList.remove(CollapseService.CLASSNAME.SHOW); | ||
element.style.height = '0' ; | ||
}); | ||
} else { | ||
this.onHideTransitionEnd(element); | ||
if (this._config.toggle) { | ||
this.toggle() | ||
} | ||
Data.setData(element, DATA_KEY, this) | ||
} | ||
public static hideAll(elements: NodeListOf<HTMLElement> | Array<HTMLElement>) { | ||
elements.forEach((element: HTMLElement) => { | ||
this.hide(element); | ||
}); | ||
// Getters | ||
static get VERSION() { | ||
return VERSION | ||
} | ||
public static isExpanded(element: HTMLElement) { | ||
return element.classList.contains(CollapseService.CLASSNAME.SHOW); | ||
static get Default() { | ||
return Default | ||
} | ||
public static isCollapsed(element: HTMLElement) { | ||
return !this.isExpanded(element); | ||
// Public | ||
public isExpanded() { | ||
return !!this._element?.classList.contains(CLASS_NAME_SHOW); | ||
} | ||
public static toggle(element: HTMLElement, animated = true) { | ||
if (this.isCollapsed(element)) { | ||
this.show(element, animated); | ||
public isCollapsed() { | ||
return !this.isExpanded(); | ||
} | ||
toggle() { | ||
if (this.isExpanded()) { | ||
this.hide() | ||
} else { | ||
this.hide(element, animated); | ||
this.show() | ||
} | ||
} | ||
protected static onShowTransitionEnd(element: HTMLElement) { | ||
setTimeout(() => { | ||
element.classList.add(CollapseService.CLASSNAME.COLLAPSE); | ||
element.classList.add(CollapseService.CLASSNAME.SHOW); | ||
element.classList.remove(CollapseService.CLASSNAME.COLLAPSING); | ||
element.style.height = ''; | ||
element.dispatchEvent(new Event(CollapseService.EVENT.SHOWN)); | ||
}); | ||
} | ||
show() { | ||
protected static onHideTransitionEnd(element: HTMLElement) { | ||
setTimeout(() => { | ||
element.classList.add(CollapseService.CLASSNAME.COLLAPSE); | ||
element.classList.remove(CollapseService.CLASSNAME.COLLAPSING); | ||
element.classList.remove(CollapseService.CLASSNAME.SHOW); | ||
element.style.height = ''; | ||
element.dispatchEvent(new Event(CollapseService.EVENT.HIDDEN)); | ||
}); | ||
if (!this._element) { | ||
console.warn('this._element not set!'); | ||
return; | ||
} | ||
if (this._isTransitioning || | ||
this._element.classList.contains(CLASS_NAME_SHOW)) { | ||
return | ||
} | ||
let actives: HTMLElement[] | null = null; | ||
let activesData: any; | ||
if (this._parent) { | ||
actives = Array.from(SelectorEngine.find(SELECTOR_ACTIVES, this._parent)) | ||
.filter(elem => { | ||
if (typeof this._config.parent === 'string') { | ||
return elem.getAttribute('data-parent') === this._config.parent | ||
} | ||
return elem.classList.contains(CLASS_NAME_COLLAPSE) | ||
}) as HTMLElement[]; | ||
if (actives.length === 0) { | ||
actives = null | ||
} | ||
} | ||
const container = this._selector ? SelectorEngine.findOne(this._selector) : null; | ||
if (actives) { | ||
const tempActiveData = actives.filter(elem => container !== elem) | ||
activesData = tempActiveData[0] ? Data.getData(tempActiveData[0], DATA_KEY) : null | ||
if (activesData && activesData._isTransitioning) { | ||
return | ||
} | ||
} | ||
const startEvent = EventHandler.trigger(this._element, EVENT_SHOW) | ||
if (startEvent.defaultPrevented) { | ||
return | ||
} | ||
if (actives) { | ||
actives.forEach(elemActive => { | ||
if (container !== elemActive) { | ||
CollapseService.collapseInterface(elemActive, 'hide') | ||
} | ||
if (!activesData) { | ||
Data.setData(elemActive, DATA_KEY, null) | ||
} | ||
}) | ||
} | ||
const dimension = this._getDimension() | ||
this._element.classList.remove(CLASS_NAME_COLLAPSE) | ||
this._element.classList.add(CLASS_NAME_COLLAPSING) | ||
this._element.style[dimension] = '0' | ||
if (this._triggerArray?.length) { | ||
this._triggerArray.forEach(element => { | ||
element.classList.remove(CLASS_NAME_COLLAPSED) | ||
element.setAttribute('aria-expanded', 'true') | ||
}) | ||
} | ||
this.setTransitioning(true) | ||
const complete = () => { | ||
if (!this._element) { | ||
console.warn('this._element not set!'); | ||
return; | ||
} | ||
this._element.classList.remove(CLASS_NAME_COLLAPSING) | ||
this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW) | ||
this._element.style[dimension] = '' | ||
this.setTransitioning(false) | ||
EventHandler.trigger(this._element, EVENT_SHOWN) | ||
} | ||
const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1) | ||
const scrollSize = `scroll${capitalizedDimension}` as 'scrollWidth' | 'scrollHeight'; | ||
const transitionDuration = Utils.getTransitionDurationFromElement(this._element) | ||
EventHandler.one(this._element, TRANSITION_END, complete) | ||
Utils.emulateTransitionEnd(this._element, transitionDuration) | ||
this._element.style[dimension] = `${this._element[scrollSize]}px` | ||
if (!this._config.parent && this._triggerArray) { | ||
this._addAriaAndCollapsedClass(this._element, this._triggerArray, true) | ||
// this._addAriaAndCollapsedClass(this._element, []) | ||
} | ||
} | ||
protected targets: NodeListOf<HTMLElement> | Array<HTMLElement>; | ||
hide() { | ||
constructor(targets: NodeListOf<HTMLElement> | Array<HTMLElement>) { | ||
this.targets = targets; | ||
if (!this._element) { | ||
console.warn('this._element not set!'); | ||
return; | ||
} | ||
if (this._isTransitioning || | ||
!this._element.classList.contains(CLASS_NAME_SHOW)) { | ||
return | ||
} | ||
const startEvent = EventHandler.trigger(this._element, EVENT_HIDE) | ||
if (startEvent.defaultPrevented) { | ||
return | ||
} | ||
const dimension = this._getDimension() | ||
this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px` | ||
Utils.reflow(this._element) | ||
this._element.classList.add(CLASS_NAME_COLLAPSING) | ||
this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW) | ||
const triggerArrayLength = this._triggerArray?.length | ||
if (triggerArrayLength && this._triggerArray && triggerArrayLength > 0) { | ||
for (let i = 0; i < triggerArrayLength; i++) { | ||
const trigger = this._triggerArray[i] | ||
const elem = Utils.getElementFromSelector(trigger) | ||
if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) { | ||
trigger.classList.add(CLASS_NAME_COLLAPSED) | ||
trigger.setAttribute('aria-expanded', 'false') | ||
} | ||
} | ||
} | ||
this.setTransitioning(true) | ||
const complete = () => { | ||
this.setTransitioning(false); | ||
if (!this._element) { | ||
console.warn('this._element not set!'); | ||
return; | ||
} | ||
this._element.classList.remove(CLASS_NAME_COLLAPSING) | ||
this._element.classList.add(CLASS_NAME_COLLAPSE) | ||
EventHandler.trigger(this._element, EVENT_HIDDEN) | ||
} | ||
this._element.style[dimension] = '' | ||
const transitionDuration = Utils.getTransitionDurationFromElement(this._element) | ||
EventHandler.one(this._element, TRANSITION_END, complete) | ||
Utils.emulateTransitionEnd(this._element, transitionDuration); | ||
if (!this._config.parent && this._triggerArray) { | ||
this._addAriaAndCollapsedClass(this._element, this._triggerArray, false) | ||
// this._addAriaAndCollapsedClass(this._element, []) | ||
} | ||
} | ||
/** | ||
* Show all | ||
*/ | ||
public show(animated = true) { | ||
this.targets.forEach((target: HTMLElement) => { | ||
CollapseService.show(target, animated); | ||
}); | ||
setTransitioning(isTransitioning: boolean) { | ||
this._isTransitioning = isTransitioning | ||
} | ||
/** | ||
* Collapse / hide all | ||
*/ | ||
public hide(animated = true) { | ||
this.targets.forEach((target: HTMLElement) => { | ||
CollapseService.hide(target, animated); | ||
}); | ||
dispose() { | ||
if (this._element) { | ||
Data.removeData(this._element, DATA_KEY); | ||
} | ||
this._config = null | ||
this._parent = null | ||
this._element = null | ||
// this._triggerArray = null | ||
this._isTransitioning = false | ||
} | ||
public isExpanded() { | ||
return CollapseService.isExpanded(this.targets[0]); | ||
// Private | ||
_getConfig(config: Partial<Config>): Config { | ||
config = { | ||
...Default, | ||
...config | ||
} | ||
config.toggle = Boolean(config.toggle) // Coerce string values | ||
Utils.typeCheckConfig(NAME, config, DefaultType) | ||
return config as Config | ||
} | ||
public isCollapsed() { | ||
return !this.isExpanded(); | ||
_getDimension() { | ||
const hasWidth = this._element ? this._element.classList.contains(WIDTH) : false; | ||
return hasWidth ? WIDTH : HEIGHT | ||
} | ||
public toggle(animated = true) { | ||
if (this.isCollapsed()) { | ||
this.show(animated); | ||
_getParent() { | ||
let { parent } = this._config | ||
if (Utils.isElement(parent)) { | ||
// it's a jQuery object | ||
if (typeof parent.jquery !== 'undefined' || typeof parent[0] !== 'undefined') { | ||
parent = parent[0] | ||
} | ||
} else { | ||
this.hide(animated); | ||
parent = SelectorEngine.findOne(parent) | ||
} | ||
// const selector = `${SELECTOR_DATA_TOGGLE}[data-parent="${parent}"]` | ||
const selector = `[data-parent="${parent}"]` | ||
SelectorEngine.find(selector, parent) | ||
.forEach(element => { | ||
const selected = Utils.getElementFromSelector(element) | ||
if (selected) { | ||
this._addAriaAndCollapsedClass( | ||
selected, | ||
[element] | ||
) | ||
} else { | ||
console.warn(); | ||
} | ||
}) | ||
return parent | ||
} | ||
_addAriaAndCollapsedClass(element: HTMLElement, triggerArray: HTMLElement[], isOpen?: boolean) { | ||
// console.debug('_addAriaAndCollapsedClass', element, triggerArray); | ||
if (element) { | ||
if (typeof isOpen !== 'boolean') { | ||
isOpen = element.classList.contains(CLASS_NAME_SHOW) | ||
} | ||
if (triggerArray.length) { | ||
triggerArray.forEach(elem => { | ||
if (isOpen) { | ||
elem.classList.remove(CLASS_NAME_COLLAPSED) | ||
} else { | ||
elem.classList.add(CLASS_NAME_COLLAPSED) | ||
} | ||
elem.setAttribute('aria-expanded', (!!isOpen).toString()) | ||
}) | ||
} | ||
} | ||
} | ||
// Static | ||
static collapseInterface(element: HTMLElement, config: string) { | ||
let data = Data.getData(element, DATA_KEY) | ||
const _config: Config = { | ||
...Default, | ||
...element.dataset, | ||
...typeof config === 'object' && config ? config : {} | ||
} | ||
if (!data && _config.toggle && /show|hide/.test(config)) { | ||
_config.toggle = false | ||
} | ||
if (!data) { | ||
data = new CollapseService(element, [], _config) | ||
} | ||
if (typeof config === 'string') { | ||
if (typeof data[config] === 'undefined') { | ||
throw new TypeError(`No method named "${config}"`) | ||
} | ||
data[config]() | ||
} | ||
} | ||
static getInstance(element: HTMLElement) { | ||
return Data.getData(element, DATA_KEY) | ||
} | ||
} |
@@ -1,2 +0,5 @@ | ||
export * from './dropdown.service'; | ||
export * from './dom'; | ||
export * from './carousel.service'; | ||
export { CollapseService } from './collapse.service'; | ||
export { DropdownService } from './dropdown.service'; | ||
export * from './utils.service'; |
@@ -5,7 +5,9 @@ import { | ||
const MILLISECONDS_MULTIPLIER = 1000; | ||
export const MAX_UID = 1000000 | ||
export const MILLISECONDS_MULTIPLIER = 1000 | ||
export const TRANSITION_END = 'transitionend' | ||
/** | ||
* | ||
* @see https://github.com/twbs/bootstrap/blob/v4-dev/js/src/util.js#L124 | ||
* @see https://github.com/twbs/bootstrap/blob/master/js/src/util/index.js | ||
*/ | ||
@@ -23,6 +25,71 @@ export class Utils extends RibaUtils { | ||
/** | ||
* | ||
* @see https://github.com/twbs/bootstrap/blob/v4-dev/js/src/util.js#L124 | ||
*/ | ||
public static getUID(prefix: string) { | ||
do { | ||
prefix += ~~(Math.random() * MAX_UID) // "~~" acts like a faster Math.floor() here | ||
} while (document.getElementById(prefix)) | ||
return prefix | ||
} | ||
public static getSelector(element: HTMLElement) { | ||
let selector = element.getAttribute('data-target') | ||
if (!selector || selector === '#') { | ||
const hrefAttr = element.getAttribute('href') | ||
selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null | ||
} | ||
return selector | ||
} | ||
public static getSelectorFromElement(element: HTMLElement) { | ||
const selector = Utils.getSelector(element) | ||
if (selector) { | ||
return document.querySelector(selector) ? selector : null | ||
} | ||
return null | ||
} | ||
public static getElementFromSelector(element: HTMLElement) { | ||
const selector = Utils.getSelector(element) | ||
return (selector ? document.querySelector(selector) : null) as HTMLElement | null; | ||
} | ||
public static getTransitionDurationFromElement(element: HTMLElement) { | ||
if (!element) { | ||
return 0 | ||
} | ||
// Get transition-duration of the element | ||
let { | ||
transitionDuration, | ||
transitionDelay | ||
} = window.getComputedStyle(element) | ||
const floatTransitionDuration = parseFloat(transitionDuration) | ||
const floatTransitionDelay = parseFloat(transitionDelay) | ||
// Return 0 if element or transition duration is not found | ||
if (!floatTransitionDuration && !floatTransitionDelay) { | ||
return 0 | ||
} | ||
// If multiple durations are defined, take the first | ||
transitionDuration = transitionDuration.split(',')[0] | ||
transitionDelay = transitionDelay.split(',')[0] | ||
return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER | ||
} | ||
public static triggerTransitionEnd(element: HTMLElement) { | ||
const evt = document.createEvent('HTMLEvents') | ||
evt.initEvent(TRANSITION_END, true, true) | ||
element.dispatchEvent(evt) | ||
} | ||
public static isElement(obj: Element | Element[]) { | ||
@@ -32,2 +99,19 @@ return ((obj as Element[])[0] || obj as Element).nodeType; | ||
public static emulateTransitionEnd = (element: HTMLElement, duration: number) => { | ||
let called = false | ||
const durationPadding = 5 | ||
const emulatedDuration = duration + durationPadding | ||
function listener() { | ||
called = true | ||
element.removeEventListener(TRANSITION_END, listener) | ||
} | ||
element.addEventListener(TRANSITION_END, listener) | ||
setTimeout(() => { | ||
if (!called) { | ||
Utils.triggerTransitionEnd(element) | ||
} | ||
}, emulatedDuration) | ||
} | ||
/** | ||
@@ -56,23 +140,68 @@ * | ||
// https://github.com/twbs/bootstrap/blob/master/dist/js/bootstrap.bundle.js#L137 | ||
public static getTransitionDurationFromElement(element: HTMLElement) { | ||
public static makeArray(nodeList: NodeList | HTMLCollection): HTMLElement[] { | ||
if (!nodeList) { | ||
return [] | ||
} | ||
return [].slice.call(nodeList) | ||
} | ||
public static isVisible(element: HTMLElement) { | ||
if (!element) { | ||
return 0; | ||
} // Get transition-duration of the element | ||
return false | ||
} | ||
if (element.style && element.parentNode && (element.parentNode as HTMLElement).style) { | ||
const elementStyle = getComputedStyle(element) | ||
const parentNodeStyle = getComputedStyle(element.parentNode as HTMLElement) | ||
return elementStyle.display !== 'none' && | ||
parentNodeStyle.display !== 'none' && | ||
elementStyle.visibility !== 'hidden' | ||
} | ||
return false | ||
} | ||
public static findShadowRoot(element: HTMLElement | Node & ParentNode): HTMLElement | Node & ParentNode | null { | ||
if (!document.documentElement.attachShadow) { | ||
return null | ||
} | ||
// Can find the shadow root otherwise it'll return the document | ||
if (typeof element.getRootNode === 'function') { | ||
const root = element.getRootNode() | ||
return root instanceof ShadowRoot ? root : null | ||
} | ||
if (element instanceof ShadowRoot) { | ||
return element | ||
} | ||
// when we don't find a shadow root | ||
if (!element.parentNode) { | ||
return null | ||
} | ||
return Utils.findShadowRoot(element.parentNode) | ||
} | ||
public static noop(){ | ||
return function () {/** nothing */}; | ||
} | ||
public static reflow(element: HTMLElement){ | ||
return element.offsetHeight; | ||
} | ||
public static getjQuery = () => { | ||
const { jQuery } = (window as any) | ||
if (jQuery && !document.body.hasAttribute('data-no-jquery')) { | ||
return jQuery | ||
} | ||
return null | ||
} | ||
const _window$getComputedSt = window.getComputedStyle(element); | ||
let transitionDuration = _window$getComputedSt.transitionDuration; | ||
let transitionDelay = _window$getComputedSt.transitionDelay; | ||
const floatTransitionDuration = parseFloat(transitionDuration); | ||
const floatTransitionDelay = parseFloat(transitionDelay); // Return 0 if element or transition duration is not found | ||
if (!floatTransitionDuration && !floatTransitionDelay) { | ||
return 0; | ||
} // If multiple durations are defined, take the first | ||
transitionDuration = transitionDuration.split(',')[0]; | ||
transitionDelay = transitionDelay.split(',')[0]; | ||
return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; | ||
} | ||
} |
{ | ||
"extends": "@ribajs/tsconfig", | ||
"files": [ | ||
"src/index.ts" | ||
], | ||
"compilerOptions": { | ||
"module": "commonjs", | ||
"target": "esnext", | ||
"lib": ["es7", "dom"], | ||
"moduleResolution": "node", | ||
"typeRoots": ["./node_modules/@types", "./node_modules/@ribajs/core/src/types"], | ||
"outDir": "dist", | ||
"declaration": true, | ||
"inlineSourceMap": true, | ||
"noUnusedLocals": true, | ||
"esModuleInterop": true, | ||
"strict": true, | ||
"noImplicitAny": true, | ||
"noImplicitThis": true, | ||
"allowSyntheticDefaultImports": true | ||
}, | ||
"include": ["src"], | ||
"exclude": ["**/*.spec.ts"], | ||
"typeRoots": ["./node_modules/@types", "./src/ts/types", "./node_modules/@ribajs/core/src/types"] | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
695017
92
17099
6
24
1
1
+ Added@ribajs/cache@1.9.0-alpha.0
+ Added@ribajs/utils@1.9.0-alpha.0
+ Added@ribajs/cache@1.9.0-alpha.0(transitive)
+ Added@ribajs/core@1.9.0-alpha.0(transitive)
+ Added@ribajs/extras@1.9.0-alpha.0(transitive)
+ Added@ribajs/utils@1.9.0-alpha.0(transitive)
- Removed@ribajs/core@1.9.0(transitive)
- Removed@ribajs/extras@1.9.0(transitive)
- Removed@ribajs/utils@1.9.0(transitive)
Updated@ribajs/core@1.9.0-alpha.0
Updated@ribajs/extras@1.9.0-alpha.0
Updatedpopper.js@^1.16.1