Skip to content

Commit

Permalink
feat: control media-query via js | #19
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzodianni committed Jan 7, 2023
1 parent b11c861 commit d961851
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 6 deletions.
15 changes: 14 additions & 1 deletion src/sidebar.core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,24 @@ export const SIDEBARJS_FALLBACK_NAME = '';
export const SIDEBARJS_CONTENT = 'sidebarjs-content';
export const SIDEBARJS_TRANSITION_START = 'sidebarjs--transition-start';
export const SIDEBARJS_TRANSITION_END = 'sidebarjs--transition-end';
export const SIDEBARJS_RESPONSIVE = 'sidebarjs--responsive';
export const IS_VISIBLE = `${SIDEBARJS}--is-visible`;
export const IS_MOVING = `${SIDEBARJS}--is-moving`;
export const POSITIONS: SidebarPosition[] = [SidebarPosition.Left, SidebarPosition.Right];
export const EVENT_LISTENER_OPTIONS: AddEventListenerOptions = {passive: true};

export const MediaQuery = {
pattern: new RegExp(/((\d*\.?\d+\s*)(px|em|rem))/),
DEFAULT_BREAKPOINT: '1025px',
getValidBreakpoint(value: SidebarConfig['responsive']) {
if (this.pattern.test(value as any)) {
return value as string;
}
console.warn(`Provided invalid breakpoint value: ${value}, fallback to ${this.DEFAULT_BREAKPOINT}`);
return this.DEFAULT_BREAKPOINT;
},
};

export const enum SidebarPosition {
Left = 'left',
Right = 'right',
Expand Down Expand Up @@ -51,7 +64,7 @@ export interface SidebarConfig {
documentSwipeRange?: number;
nativeSwipe?: boolean;
nativeSwipeOpen?: boolean;
responsive?: boolean;
responsive?: boolean | string;
mainContent?: HTMLElement;
position?: SidebarPosition;
backdropOpacity?: number;
Expand Down
33 changes: 29 additions & 4 deletions src/sidebar.element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
IS_VISIBLE,
isStyleMapSupported,
MapGestureEvent,
MediaQuery,
POSITIONS,
shouldDefineMainContent,
shouldInvokeFunction,
Expand All @@ -16,6 +17,7 @@ import {
SidebarConfig,
SIDEBARJS,
SIDEBARJS_CONTENT,
SIDEBARJS_RESPONSIVE,
SIDEBARJS_TRANSITION_END,
SIDEBARJS_TRANSITION_START,
SidebarPosition,
Expand Down Expand Up @@ -52,6 +54,7 @@ export class SidebarElement implements SidebarBase {
private readonly _emitOnOpen?: CallableFunction;
private readonly _emitOnClose?: CallableFunction;
private readonly _emitOnChangeVisibility?: (changes: SidebarChangeEvent) => void;
private readonly _destroyResponsive?: () => void;

constructor(options: SidebarConfig = {}) {
const config = {...DEFAULT_CONFIG, ...options};
Expand Down Expand Up @@ -83,7 +86,7 @@ export class SidebarElement implements SidebarBase {
this.setSwipeGestures(true);

if (this.responsive || this.mainContent) {
this.setResponsive();
this._destroyResponsive = this.setResponsive(config.responsive);
}

this.setPosition(config.position!);
Expand Down Expand Up @@ -117,12 +120,13 @@ export class SidebarElement implements SidebarBase {
this.backdrop.removeEventListener('click', this.close);
this.removeNativeOpenGestures();
this.removeAttrsEventsListeners(this.component.getAttribute(SIDEBARJS)!);
this.removeComponentClassPosition();
this.removeComponentClassPosition(true);
while (this.container.firstElementChild) {
this.component.appendChild(this.container.firstElementChild);
}
this.component.removeChild(this.container);
this.component.removeChild(this.backdrop);
this._destroyResponsive?.();
Object.keys(this).forEach((key) => ((this as any)[key] = null));
}

Expand Down Expand Up @@ -343,14 +347,35 @@ export class SidebarElement implements SidebarBase {
this.applyStyle(this.backdrop, 'opacity', opacity.toString());
}

private setResponsive(): void {
private setResponsive(breakpoint?: SidebarConfig['responsive']) {
if (!this.responsive && this.mainContent) {
throw new Error(`You provide a [${SIDEBARJS_CONTENT}] element without set {responsive: true}`);
}
if (this.responsive && !this.mainContent) {
throw new Error(`You have set {responsive: true} without provide a [${SIDEBARJS_CONTENT}] element`);
}
this.addComponentClass('sidebarjs--responsive');
this.addComponentClass(SIDEBARJS_RESPONSIVE);
const destroyMediaQuery = this.setMediaQuery(breakpoint);
return () => {
destroyMediaQuery();
this.removeComponentClass(SIDEBARJS_RESPONSIVE);
};
}

private setMediaQuery(breakpoint?: SidebarConfig['responsive']) {
const value = MediaQuery.getValidBreakpoint(breakpoint);
const mediaQuery = window.matchMedia(`(min-width: ${value})`);
const toggleMediaQueryClass = (e: MediaQueryList | MediaQueryListEvent) => this.toggleDesktopBreakpointClass(e.matches);
mediaQuery.addEventListener('change', toggleMediaQueryClass, EVENT_LISTENER_OPTIONS);
toggleMediaQueryClass(mediaQuery);
return () => {
mediaQuery.removeEventListener('change', toggleMediaQueryClass);
this.toggleDesktopBreakpointClass(false);
}
}

private toggleDesktopBreakpointClass(isDesktop: boolean) {
document.body.classList.toggle('sidebarjs--desktop-breakpoint', isDesktop);
}

private applyStyle(el: HTMLElement, prop: CSSStyleProperties, val: CSSStyleValues, vendorify?: boolean): void {
Expand Down
13 changes: 12 additions & 1 deletion src/sidebarjs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ $width: 300px;

[sidebarjs].sidebarjs--left {
@extend %component--left;

[sidebarjs-container] {
@extend %component--left;
@include shadow('left');
Expand All @@ -45,6 +46,7 @@ $width: 300px;

[sidebarjs].sidebarjs--right {
@extend %component--right;

[sidebarjs-container] {
@extend %component--right;
@include shadow('right');
Expand Down Expand Up @@ -87,6 +89,7 @@ $width: 300px;
&.sidebarjs--is-moving {
transition: none;
transform: translate(0, 0);

[sidebarjs-container], [sidebarjs-backdrop] {
transition: none;
}
Expand All @@ -98,34 +101,41 @@ $width: 300px;
width: 100%;
min-height: 100%;
transition: width $duration $timing;

&.sidebarjs-content--left {
margin-left: auto;
margin-right: 0;
}

&.sidebarjs-content--right {
margin-left: 0;
margin-right: auto;
}
}

@media (min-width: 1025px) {
.sidebarjs--desktop-breakpoint {
[sidebarjs].sidebarjs--responsive {
@include component--is-visible(!important);
width: $width;

&.sidebarjs--left {
left: 0;
right: auto;

[sidebarjs-container] {
box-shadow: 1px 0 0 rgba(black, .1);
}
}

&.sidebarjs--right {
right: 0;
left: auto;

[sidebarjs-container] {
box-shadow: -1px 0 0 rgba(black, .1);
}
}

[sidebarjs-container] {
max-width: none;
width: 100%;
Expand All @@ -135,6 +145,7 @@ $width: 300px;

[sidebarjs-content] {
width: calc(100% - #{$width});

&.sidebarjs-content--left.sidebarjs-content--right {
width: calc(100% - #{$width*2});
margin: 0 auto;
Expand Down

0 comments on commit d961851

Please sign in to comment.