ionic-react-header-parallax
Advanced tools
Comparing version 0.0.8 to 0.1.0
@@ -24,81 +24,53 @@ "use strict"; | ||
const React = __importStar(require("react")); | ||
function useIonHeaderParallax({ titleColor, image, expandedColor, maximumHeight = 300, }) { | ||
let header; | ||
let toolbar; | ||
let toolbarBackground; | ||
let imageOverlay; | ||
let colorOverlay; | ||
let barButtons; | ||
let scrollContent; | ||
let headerHeight; | ||
let headerMinHeight; | ||
let translateAmt; | ||
let scaleAmt; | ||
let scrollTop; | ||
let lastScrollTop; | ||
let ticking; | ||
let originalToolbarBgColor; | ||
let overlayTitle; | ||
let ionTitle; | ||
let overlayButtons; | ||
let scrollContentPaddingTop; | ||
function useIonHeaderParallax({ image, titleColor = '#AAA', expandedColor = '#313131', maximumHeight = 300, }) { | ||
/** styles */ | ||
const [ticking, setTicking] = React.useState(false); | ||
React.useEffect(() => { | ||
setTimeout(() => { | ||
try { | ||
initElements(); | ||
initStyles(); | ||
initEvents(); | ||
} | ||
catch (e) { | ||
throw e; | ||
} | ||
}, 100); | ||
}, []); | ||
initElements(); | ||
}, 200); | ||
}, [titleColor, image, expandedColor, maximumHeight]); | ||
const initElements = () => { | ||
var _a; | ||
// ion-header | ||
const header = document.getElementsByTagName('ion-header')[0]; | ||
const parentElement = header.parentElement; | ||
if (!parentElement) | ||
throw new Error('No parentElemnt'); | ||
// check this | ||
toolbar = header.querySelector('IonToolbar'); | ||
if (!toolbar) { | ||
throw new Error('Parallax requires a <IonToolbar> or navbar element on the page to work.'); | ||
} | ||
if (!toolbar.shadowRoot) { | ||
throw new Error('Parallax requires a shadowRoot <IonToolbar>'); | ||
} | ||
ionTitle = toolbar.querySelector('IonTitle'); | ||
toolbarBackground = toolbar.shadowRoot.querySelector('.toolbar-background'); | ||
console.log('toolbarBackground', toolbarBackground); | ||
barButtons = header.querySelector('IonButtons'); | ||
const ionContent = parentElement.querySelector('IonContent'); | ||
throw new Error('No IonPage parent element'); | ||
// ion-toolbar | ||
const toolbar = header.querySelector('ion-toolbar'); | ||
if (!toolbar) | ||
throw new Error('No <ion-toolbar>'); | ||
// ion-toolbar background | ||
const toolbarShadowRoot = toolbar.shadowRoot; | ||
// if (!toolbarShadowRoot) throw new Error('No shadow') | ||
const toolbarBackground = toolbarShadowRoot === null || toolbarShadowRoot === void 0 ? void 0 : toolbarShadowRoot.querySelector('.toolbar-background'); | ||
// if (!toolbarBackground) throw new Error('No .toolbar-background') | ||
// ion-title | ||
const ionTitle = toolbar.querySelector('ion-title'); | ||
// ion-buttons | ||
const barButtons = header.querySelector('ion-buttons'); | ||
// ion-content | ||
const ionContent = parentElement.querySelector('ion-content'); | ||
if (!ionContent) | ||
throw new Error('Parallax directive requires an <IonContent> element on the page to work.'); | ||
if (!ionContent.shadowRoot) | ||
throw new Error('Parallax requires a shadowRoot <ion-content>'); | ||
scrollContent = ionContent.shadowRoot.querySelector('.inner-scroll'); | ||
if (!scrollContent) { | ||
throw new Error('Parallax directive requires an <IonContent> element on the page to work.'); | ||
} | ||
headerHeight = scrollContent.clientHeight; | ||
console.log('headerHeight', headerHeight); | ||
// Create image overlay | ||
imageOverlay = document.createElement('div'); | ||
console.log('imageOverlay', imageOverlay); | ||
throw new Error('Parallax an <ion-content> element on the page to work.'); | ||
const scrollContent = (_a = ionContent.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.inner-scroll'); | ||
// create image overly | ||
const imageOverlay = document.createElement('div'); | ||
imageOverlay.classList.add('image-overlay'); | ||
colorOverlay = document.createElement('div'); | ||
const colorOverlay = document.createElement('div'); | ||
colorOverlay.classList.add('color-overlay'); | ||
colorOverlay.appendChild(imageOverlay); | ||
header.appendChild(colorOverlay); | ||
// Copy title and buttons | ||
overlayTitle = ionTitle && ionTitle.cloneNode(true); | ||
if (!overlayTitle) | ||
throw new Error(''); | ||
overlayTitle.classList.add('parallax-title'); | ||
setTimeout(() => { | ||
var _a; | ||
const toolbarTitle = (_a = overlayTitle === null || overlayTitle === void 0 ? void 0 : overlayTitle.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.toolbar-title'); | ||
toolbarTitle.style.pointerEvents = 'unset'; | ||
}); | ||
const overlayTitle = ionTitle && ionTitle.cloneNode(true); | ||
if (overlayTitle) { | ||
overlayTitle.classList.add('parallax-title'); | ||
setTimeout(() => { | ||
if (overlayTitle.shadowRoot) { | ||
const toolbarTitle = overlayTitle.shadowRoot.querySelector('.toolbar-title'); | ||
toolbarTitle.style.pointerEvents = 'unset'; | ||
} | ||
}, 200); | ||
} | ||
if (overlayTitle) { | ||
imageOverlay.appendChild(overlayTitle); | ||
@@ -109,23 +81,20 @@ } | ||
} | ||
console.log('finished'); | ||
}; | ||
const initStyles = () => { | ||
ticking = false; | ||
if (!scrollContent || !toolbar) { | ||
return; | ||
} | ||
/*** initStyles ***/ | ||
// still in init use JS DOM | ||
let headerHeight = scrollContent === null || scrollContent === void 0 ? void 0 : scrollContent.clientHeight; | ||
setTicking(false); | ||
// fetch styles | ||
headerMinHeight = toolbar.offsetHeight; | ||
scrollContentPaddingTop = window.getComputedStyle(scrollContent, null).paddingTop.replace('px', ''); | ||
scrollContentPaddingTop = parseFloat(scrollContentPaddingTop); | ||
if (!toolbarBackground) | ||
return; | ||
originalToolbarBgColor = window.getComputedStyle(toolbarBackground, null).backgroundColor; | ||
if (!originalToolbarBgColor) { | ||
throw new Error('Error: toolbarBackround is null.'); | ||
maximumHeight = parseFloat(maximumHeight.toString()); | ||
let headerMinHeight = toolbar.offsetHeight; | ||
let scrollContentPaddingTop = 0; | ||
if (scrollContent) { | ||
scrollContentPaddingTop = parseFloat(window.getComputedStyle(scrollContent, null).paddingTop.replace('px', '')); | ||
} | ||
let originalToolbarBgColor = 'white'; | ||
if (toolbarBackground) { | ||
originalToolbarBgColor = window.getComputedStyle(toolbarBackground, null).backgroundColor; | ||
} | ||
// header and title | ||
header.style.position = 'relative'; | ||
if (overlayTitle) { | ||
// rerender here | ||
overlayTitle.style.color = titleColor; | ||
@@ -148,3 +117,3 @@ overlayTitle.style.position = 'absolute'; | ||
imageOverlay.style.backgroundColor = expandedColor; | ||
imageOverlay.style.backgroundImage = `url(${image || ''})`; | ||
imageOverlay.style.backgroundImage = `url(${image})`; | ||
imageOverlay.style.height = '100%'; | ||
@@ -155,30 +124,78 @@ imageOverlay.style.width = '100%'; | ||
imageOverlay.style.backgroundPosition = 'center'; | ||
}; | ||
const initEvents = () => { }; | ||
const onScroll = (_ev) => { | ||
if (!scrollContent || !toolbar) { | ||
return; | ||
// .toolbar-background | ||
if (toolbarBackground) { | ||
toolbarBackground.style.backgroundColor = originalToolbarBgColor; | ||
} | ||
scrollTop = scrollContent.scrollTop; | ||
if (scrollTop >= 0) { | ||
translateAmt = scrollTop / 2; | ||
scaleAmt = 1; | ||
// .bar-buttons | ||
if (barButtons) { | ||
barButtons.style.pointerEvents = 'all'; | ||
Array.from(barButtons.children).forEach((btn) => { | ||
console.log(btn, btn); | ||
const htmlBtn = btn; | ||
htmlBtn.style.color = titleColor; | ||
}); | ||
} | ||
else { | ||
translateAmt = 0; | ||
scaleAmt = -scrollTop / headerHeight + 1; | ||
// .scroll-content | ||
if (scrollContent) { | ||
scrollContent.setAttribute('parallax', ''); | ||
scrollContent.style.paddingTop = `${maximumHeight + scrollContentPaddingTop - headerMinHeight}px`; | ||
} | ||
// Parallax total progress | ||
headerMinHeight = toolbar.offsetHeight; | ||
let progress = (maximumHeight - scrollTop - headerMinHeight) / (maximumHeight - headerMinHeight); | ||
progress = Math.max(progress, 0); | ||
// ion-header: set height | ||
let targetHeight = maximumHeight - scrollTop; | ||
targetHeight = Math.max(targetHeight, headerMinHeight); | ||
console.log(lastScrollTop, ticking, overlayButtons, translateAmt, scaleAmt); | ||
/** init events */ | ||
window.addEventListener('resize', () => { | ||
headerHeight = scrollContent.clientHeight; | ||
}, false); | ||
if (scrollContent) { | ||
scrollContent.addEventListener('scroll', (_e) => { | ||
if (!ticking) { | ||
window.requestAnimationFrame(() => { | ||
// to do | ||
const scrollTop = scrollContent.scrollTop; | ||
let translateAmt; | ||
let scaleAmt; | ||
if (scrollTop >= 0) { | ||
translateAmt = scrollTop / 2; | ||
scaleAmt = 1; | ||
} | ||
else { | ||
translateAmt = 0; | ||
scaleAmt = scrollTop / headerHeight + 1; | ||
} | ||
// Parallax total progress | ||
headerMinHeight = toolbar.offsetHeight; | ||
let progress = (maximumHeight - scrollTop - headerMinHeight) / (maximumHeight - headerMinHeight); | ||
progress = Math.max(progress, 0); | ||
let targetHeight = maximumHeight - scrollTop; | ||
targetHeight = Math.max(targetHeight, headerMinHeight); | ||
header.style.transform = 'translate3d(0,' + translateAmt + 'px,0) scale(' + scaleAmt + ',' + scaleAmt + ')'; | ||
// .toolbar-background: change color | ||
imageOverlay.style.height = `${targetHeight}px`; | ||
imageOverlay.style.opacity = `${progress}`; | ||
colorOverlay.style.height = `${targetHeight}px`; | ||
colorOverlay.style.opacity = targetHeight > headerMinHeight ? '1' : '0'; | ||
toolbarBackground.style.backgroundColor = | ||
targetHeight > headerMinHeight ? 'transparent' : originalToolbarBgColor; | ||
// .bar-buttons | ||
if (barButtons) { | ||
if (targetHeight > headerMinHeight) { | ||
imageOverlay.append(barButtons); | ||
Array.from(barButtons.children).forEach((btn) => { | ||
const htmlBtn = btn; | ||
htmlBtn.style.color = titleColor; | ||
}); | ||
} | ||
else { | ||
toolbar.append(barButtons); | ||
Array.from(barButtons.children).forEach((btn) => { | ||
const htmlBtn = btn; | ||
htmlBtn.style.color = 'unset'; | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
setTicking(true); | ||
}); | ||
} | ||
}; | ||
return { | ||
onScroll, | ||
}; | ||
} | ||
exports.useIonHeaderParallax = useIonHeaderParallax; |
{ | ||
"name": "ionic-react-header-parallax", | ||
"version": "0.0.8", | ||
"version": "0.1.0", | ||
"description": "A React Hook parallax effect for Ionic React <IonHeader> component", | ||
@@ -53,20 +53,21 @@ "author": { | ||
"devDependencies": { | ||
"@babel/preset-env": "^7.15.0", | ||
"@babel/preset-react": "^7.14.5", | ||
"@babel/preset-typescript": "^7.15.0", | ||
"@ionic/react": "^5.6.14", | ||
"@testing-library/react": "^12.0.0", | ||
"@types/jest": "^26", | ||
"@types/node": "^16.6.1", | ||
"@types/react": "^17.0.18", | ||
"auto-changelog": "^2.3.0", | ||
"@babel/preset-env": "7.15.0", | ||
"@babel/preset-react": "7.14.5", | ||
"@babel/preset-typescript": "7.15.0", | ||
"@ionic/react": "5.6.14", | ||
"@testing-library/react": "12.0.0", | ||
"@types/jest": "26.0.24", | ||
"@types/node": "16.6.2", | ||
"@types/react": "17.0.19", | ||
"auto-changelog": "2.3.0", | ||
"babel-jest": "26.6.0", | ||
"codecov": "^3.8.3", | ||
"eslint": "^7.32.0", | ||
"jest": "^26.6.0", | ||
"np": "^7.5.0", | ||
"prettier": "^2.3.2", | ||
"codecov": "3.8.3", | ||
"eslint": "7.32.0", | ||
"jest": "26.6.3", | ||
"np": "7.5.0", | ||
"prettier": "2.3.2", | ||
"react": "^17.0.2", | ||
"react-dom": "^17.0.2", | ||
"rimraf": "^3.0.2", | ||
"testing-library__dom": "^7.29.4-beta.1", | ||
"ts-jest": "^26", | ||
@@ -73,0 +74,0 @@ "ts-node": "^10.2.0", |
export type UseIonHeaderParallaxInput = { | ||
image: string | ||
expandedColor: string | ||
titleColor: string | ||
expandedColor?: string | ||
titleColor?: string | ||
maximumHeight?: number | ||
} | ||
export type UseIonHeaderParallaxResult = { | ||
ref: React.MutableRefObject<HTMLElement | null> | ||
onScroll: () => void | ||
} | ||
export type UseIonHeaderParallaxResult = void | ||
export type IonHeaderParallaxProps = { | ||
image: string | ||
expandedColor?: string | ||
originalToolbarBgColor: string | ||
maximumHeight: number | ||
headerMinHeight: number | ||
} | ||
export const IonHeaderParallax: React.FC<React.PropsWithChildren<IonHeaderParallaxProps>> | ||
export function useIonHeaderParallax(input: UseIonHeaderParallaxInput): UseIonHeaderParallaxResult |
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 bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
18472
22
7
210
1