-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial Commit * QuirkBoomerand - added POC * Quirk-Boomerang code update * Minor changes * code imorvment - used method directly instead of creating variable * fix: move quirk forward gliches * updated code to deletct scroll end * QuirkBoomerang - added support to move backward * QuirkBoomerang - manage visibility of move buttons * QuirkBoomerang - fix: move button visibility code * QuirkBoomerang - fix: move issue - 1 display count * QuirkBoomrang - check elm in parent & viewport * fix: move button visibility * added styles to move buttons * removed shadowDom setting - default set to false * commnted tests * scrollTimeout clear interval code update * added support for keyboard navigation * support=>btn inaccessible behaviour->hide|disable * fix: issue with move backward * style: chnage for element height & btn cursor * chore: index.html change * chore: updated library version
- Loading branch information
Showing
11 changed files
with
12,099 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
.quirk-boomerang-container { | ||
position: relative; | ||
/* margin-left: 1.4em; | ||
margin-right: 1.4em; */ | ||
} | ||
|
||
.quirk-boomerang-container .move-btns { | ||
display: flex; | ||
justify-content: space-between; | ||
} | ||
|
||
.quirk-boomerang-container .move-btns button { | ||
width: 3rem; | ||
height: 3rem; | ||
cursor: pointer; | ||
border-radius: 2rem; | ||
} | ||
|
||
.quirk-boomerang-container .move-btns button:focus { | ||
outline: inherit; | ||
} | ||
|
||
.quirk-boomerang-container .move-btns .move-btn-wrapper { | ||
z-index: 1; | ||
position: absolute; | ||
top: calc(50% - calc(3rem - 22px)); | ||
} | ||
|
||
.quirk-boomerang-container .move-btns .backward-move-btn-wrapper { | ||
left: 0; | ||
} | ||
|
||
.quirk-boomerang-container .move-btns .forward-move-btn-wrapper { | ||
right: 0; | ||
} | ||
|
||
.quirk-boomerang-container .quirk-container { | ||
overflow-x: hidden; | ||
display: grid; | ||
grid-auto-flow: column; | ||
/* grid-template-columns: 70%; | ||
grid-auto-columns: 70%; */ | ||
scroll-snap-type: x mandatory; | ||
} | ||
|
||
.quirk-boomerang-container .quirk-container > * { | ||
padding: 1em; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
scroll-snap-align: start; | ||
} | ||
|
||
.quirk-boomerang-container .quirk-container > * > * { | ||
max-width: calc(100% - 1rem); | ||
max-height: calc(100vh - 3rem); | ||
} | ||
|
||
/* Small devices (landscape phones, 576px and up) */ | ||
@media (max-width: 767.9px) { | ||
.quirk-boomerang-container .quirk-container { | ||
/* overflow-x: scroll; */ | ||
grid-template-columns: repeat(var(--quirk-small-count), calc(100% / var(--quirk-small-count))); | ||
grid-auto-columns: calc(100% / var(--quirk-small-count)); | ||
} | ||
} | ||
|
||
/* Medium devices (tablets, 768px and up) */ | ||
@media (min-width: 768px) { | ||
.quirk-boomerang-container .quirk-container { | ||
/* overflow-x: scroll; */ | ||
grid-template-columns: repeat(var(--quirk-medium-count), calc(100% / var(--quirk-medium-count))); | ||
grid-auto-columns: calc(100% / var(--quirk-medium-count)); | ||
} | ||
} | ||
|
||
/* Large devices (desktops, 992px and up) or Extra large devices (large desktops, 1200px and up) */ | ||
@media (min-width: 992px), (min-width: 1200px) { | ||
.quirk-boomerang-container .quirk-container { | ||
overflow-x: hidden; | ||
grid-template-columns: repeat(var(--quirk-large-count), calc(100% / var(--quirk-large-count))); | ||
grid-auto-columns: calc(100% / var(--quirk-large-count)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
import { Component, h, Method, Prop, State, Element } from '@stencil/core'; | ||
import { isElementVisibleInViewportAndParent } from '../../utils/utils'; | ||
|
||
@Component({ | ||
tag: 'quirk-boomerang', | ||
styleUrl: 'quirk-boomerang.css', | ||
}) | ||
export class QuirkBoomerang { | ||
@Element() quirkEl: HTMLElement; | ||
@Prop() moveCount: number = 1; | ||
@Prop() totalElements: number = 0; | ||
@Prop() displayCount: | ||
| { small: string, medium: string, large: string } | ||
| string | number = { small: "1", medium: "2", large: "4" }; | ||
@Prop() moveButtonInaccessibleBehaviour: "disable" | "hide" = "disable"; | ||
|
||
@State() lastMovedElement: Element; | ||
@State() moveDirection: "forward" | "backward"; | ||
@State() visibleMoveButton = { forward: true, backward: false }; | ||
scrollTimeoutId: number; | ||
|
||
get quirkContainerEl() { | ||
return this.quirkEl.querySelector("quirk-boomerang .quirk-container"); | ||
} | ||
|
||
get visibleQuirks() { | ||
return this.quirkContainerEl.querySelectorAll(".quirk-visible"); | ||
} | ||
|
||
get quirkCount() { | ||
let count = 1; | ||
|
||
try { | ||
if (typeof this.displayCount === "object") { | ||
return this.displayCount; | ||
} | ||
|
||
if (isNaN(this.displayCount as number)) { | ||
return JSON.parse(this.displayCount as string); | ||
} else { | ||
count = +this.displayCount; | ||
} | ||
} catch (error) { | ||
console.warn("Set proper value for displayCount prop. Error: ", error) | ||
} | ||
|
||
return { small: count, medium: count, large: count }; | ||
} | ||
|
||
get elementCount() { | ||
return (this.totalElements || document.querySelectorAll("quirk-boomerang .quirk-container > [quirk-index]").length); | ||
} | ||
|
||
get lastMovedElementIndex() { | ||
return this.lastMovedElement ? +this.lastMovedElement.getAttribute("quirk-index") : -1; | ||
} | ||
|
||
@Method() | ||
async moveQuirk(isMoveForward: boolean | undefined, moveElementIndex: number | undefined = undefined) { | ||
if (moveElementIndex) { | ||
this.moveDirection = moveElementIndex >= this.lastMovedElementIndex ? "forward" : "backward"; | ||
isMoveForward = this.moveDirection === "forward"; | ||
} else { | ||
this.moveDirection = isMoveForward ? "forward" : "backward"; | ||
} | ||
|
||
// if (this.visibleQuirks && this.visibleQuirks.length && (!moveElementIndex || (moveElementIndex && moveElementIndex !== this.lastMovedElementIndex))) { | ||
if (this.visibleQuirks && this.visibleQuirks.length) { | ||
const currentEndIndex = +this.visibleQuirks[this.visibleQuirks.length - 1].getAttribute("quirk-index"); | ||
const moveToIndex = moveElementIndex != null ? moveElementIndex | ||
: isMoveForward ? currentEndIndex + this.moveCount : currentEndIndex - this.moveCount; | ||
let moveEl = this.quirkContainerEl.querySelector(`[quirk-index="${moveToIndex}"]`) || this.quirkContainerEl.lastElementChild; | ||
|
||
if (this.lastMovedElement === moveEl) { | ||
moveEl = this.quirkContainerEl.querySelector(`[quirk-index="${moveToIndex + this.moveCount}"]`) || this.quirkContainerEl.lastElementChild; | ||
} | ||
|
||
if (moveEl) { | ||
this.lastMovedElement = moveEl; | ||
moveEl.scrollIntoView({ behavior: "smooth", block: "center", inline: "end" }); | ||
} | ||
} | ||
} | ||
|
||
setVisibleQuirks() { | ||
let visibleQuirkClassSetFailCount = 0; | ||
const isFirstRender = this.lastMovedElement == null; | ||
const lastMoveElementIndex = isFirstRender ? 0 : +this.lastMovedElement.getAttribute("quirk-index"); | ||
const isVisibleQuirksAvailable = this.visibleQuirks && this.visibleQuirks.length; | ||
const isMoveForward = this.moveDirection == null || this.moveDirection === "forward"; | ||
const firstVisibleQuirkIndex = isFirstRender ? 0 : isVisibleQuirksAvailable | ||
? +this.visibleQuirks[0].getAttribute("quirk-index") | ||
: lastMoveElementIndex; | ||
const lastVisibleQuirkIndex = isFirstRender ? this.moveCount : isVisibleQuirksAvailable | ||
? +this.visibleQuirks[this.visibleQuirks.length - 1].getAttribute("quirk-index") | ||
: lastMoveElementIndex; | ||
let index = isMoveForward ? firstVisibleQuirkIndex : lastVisibleQuirkIndex; | ||
this.quirkContainerEl.querySelectorAll("[quirk-index]").forEach(quirk => quirk.classList.remove("quirk-visible")); | ||
|
||
while (true) { | ||
const el = this.quirkContainerEl.querySelector(`[quirk-index="${index}"]`); | ||
|
||
if (el && isElementVisibleInViewportAndParent(el)) { | ||
el.classList.add("quirk-visible"); | ||
} else { | ||
visibleQuirkClassSetFailCount++; | ||
} | ||
|
||
if (isMoveForward) { | ||
index++; | ||
} else { | ||
index--; | ||
} | ||
|
||
if (visibleQuirkClassSetFailCount > this.elementCount) { | ||
break; | ||
} | ||
} | ||
|
||
this.setMoveButtonVisibility( | ||
isMoveForward ? firstVisibleQuirkIndex : firstVisibleQuirkIndex - this.moveCount, | ||
isMoveForward ? lastVisibleQuirkIndex + this.moveCount : lastVisibleQuirkIndex, | ||
isFirstRender | ||
); | ||
} | ||
|
||
setMoveButtonVisibility(firstVisibleQuirkIndex: number, lastVisibleQuirkIndex: number, isFirstRender: boolean) { | ||
if (!isFirstRender) { | ||
this.visibleMoveButton = { | ||
...this.visibleMoveButton, | ||
forward: lastVisibleQuirkIndex < this.elementCount - 1, | ||
backward: firstVisibleQuirkIndex > 0 | ||
} | ||
} | ||
} | ||
|
||
keyPressHandler(event: KeyboardEvent) { | ||
if (event.key === "Tab" && document.activeElement && document.activeElement.getAttribute("quirk-index")) { | ||
let moveElementIndex = +document.activeElement.getAttribute("quirk-index"); | ||
// here added 1 to make sure next element to focus is in view | ||
this.moveQuirk(undefined, moveElementIndex + 1); | ||
} | ||
} | ||
|
||
scrollEventCallback(_e: Event) { | ||
if (this.scrollTimeoutId != null) { | ||
clearTimeout(this.scrollTimeoutId); | ||
} | ||
|
||
this.scrollTimeoutId = window.setTimeout(() => { | ||
this.setVisibleQuirks(); | ||
}, 0); | ||
} | ||
|
||
componentDidLoad() { | ||
this.setVisibleQuirks(); | ||
} | ||
|
||
componentDidRender() { | ||
this.quirkContainerEl.addEventListener('scroll', this.scrollEventCallback.bind(this)); | ||
} | ||
|
||
disconnectedCallback() { | ||
this.quirkContainerEl.removeEventListener("scroll", this.scrollEventCallback.bind(this)); | ||
} | ||
|
||
render() { | ||
return ( | ||
<div class="quirk-boomerang-container"> | ||
<div class="move-btns" tabIndex={-1}> | ||
{this.moveButtonInaccessibleBehaviour === "disable" || this.visibleMoveButton.backward ? | ||
<slot name="left-button"> | ||
<div class="move-btn-wrapper backward-move-btn-wrapper"> | ||
<button | ||
class="move-btn backward-move backward-move-btn" | ||
disabled={!this.visibleMoveButton.backward} | ||
onClick={this.moveQuirk.bind(this, false, undefined)} | ||
> | ||
< | ||
</button> | ||
</div> | ||
</slot> | ||
: null | ||
} | ||
{this.moveButtonInaccessibleBehaviour === "disable" || this.visibleMoveButton.forward ? | ||
<slot name="right-button"> | ||
<div class="move-btn-wrapper forward-move-btn-wrapper"> | ||
<button | ||
class="move-btn forward-move forward-move-btn" | ||
disabled={!this.visibleMoveButton.forward} | ||
onClick={this.moveQuirk.bind(this, true, undefined)} | ||
> | ||
> | ||
</button> | ||
</div> | ||
</slot> | ||
: null | ||
} | ||
</div> | ||
<div class="quirk-container" onKeyUp={this.keyPressHandler.bind(this)} style={{ "--quirk-small-count": this.quirkCount.small, "--quirk-medium-count": this.quirkCount.medium, "--quirk-large-count": this.quirkCount.large }}> | ||
<slot></slot> | ||
</div> | ||
</div> | ||
); | ||
} | ||
} |
Oops, something went wrong.