Skip to content

Commit

Permalink
🆕 feat: Add ScrollToTarget component
Browse files Browse the repository at this point in the history
  • Loading branch information
capdiem committed Jan 22, 2024
1 parent c15dd42 commit 3e757e2
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 11 deletions.
23 changes: 23 additions & 0 deletions src/Component/BlazorComponent.Web/src/interop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,29 @@ export function scrollTo(target, options: ScrollToOptions) {
}
}

export function scrollToTarget(
target: string,
container: string = null,
offset: number = 0
) {
const targetEl: HTMLElement = document.querySelector(target);
if (targetEl) {
let top ;
if (container) {
top = targetEl.offsetTop;
} else {
top = targetEl.getBoundingClientRect().top + window.scrollY;
}
const containerEl = container
? document.querySelector(container)
: document.documentElement
containerEl.scrollTo({
top: top - offset,
behavior: "smooth",
});
}
}

export function scrollToElement(target, offset: number, behavior?: ScrollBehavior) {
const dom = getDom(target)
if (!dom) return;
Expand Down
73 changes: 64 additions & 9 deletions src/Component/BlazorComponent.Web/src/mixins/intersect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { getEventTarget } from "utils/helper";

interface IntersectionObserverOptions {
rootSelector?: string;
rootMargin?: string;
rootMarginLeft?: string;
rootMarginRight?: string;
rootMarginTop?: string;
rootMarginBottom?: string;
autoRootMargin: "None" | "Top" | "Right" | "Bottom" | "Left";
threshold: number[];
once: boolean;
}
Expand All @@ -21,23 +25,31 @@ function observe(
return;
}

if (el["_observe"]) {
return;
}

const once = options?.once ?? false;

const standardOptions = formatToStandardOptions(options);

const observer = new IntersectionObserver(
async (
entries: IntersectionObserverEntry[] = [],
observer: IntersectionObserver
) => {
const computedEntries = entries.map(entry => ({
const computedEntries = entries.map((entry) => ({
isIntersecting: entry.isIntersecting,
target: getEventTarget(entry.target)
target: getEventTarget(entry.target),
}));

const isIntersecting = computedEntries.some(e => e.isIntersecting);
const isIntersecting = computedEntries.some((e) => e.isIntersecting);

if (!once || isIntersecting) {
await handle.invokeMethodAsync("Invoke", { isIntersecting, entries: computedEntries });
await handle.invokeMethodAsync("Invoke", {
isIntersecting,
entries: computedEntries,
});
}

if (isIntersecting && once) {
Expand Down Expand Up @@ -69,6 +81,7 @@ function observeSelector(
handle: DotNet.DotNetObject,
options?: IntersectionObserverOptions
) {

if (selector) {
const el = document.querySelector(selector) as HTMLElement;
el && observe(el, handle, options);
Expand All @@ -89,13 +102,55 @@ function formatToStandardOptions(
return null;
}

const root: HTMLLIElement = options.rootSelector
? document.querySelector(options.rootSelector)
: null;

if (options.autoRootMargin !== "None") {
if (
options.autoRootMargin === "Top" &&
options.rootMarginBottom !== "0px"
) {
options.rootMarginTop =
calcAuto(root, options.rootMarginBottom, false) + "px";
} else if (
options.autoRootMargin === "Right" &&
options.rootMarginLeft !== "0px"
) {
options.rootMarginRight =
calcAuto(root, options.rootMarginLeft, false) + "px";
} else if (
options.autoRootMargin === "Bottom" &&
options.rootMarginTop !== "0px"
) {
options.rootMarginBottom =
calcAuto(root, options.rootMarginTop, false) + "px";
} else if (
options.autoRootMargin === "Left" &&
options.rootMarginRight !== "0px"
) {
options.rootMarginLeft =
calcAuto(root, options.rootMarginRight, false) + "px";
}
}

return {
rootMargin: options.rootMargin,
root: options.rootSelector
? document.querySelector(options.rootSelector)
: null,
rootMargin: `${options.rootMarginTop} ${options.rootMarginRight} ${options.rootMarginBottom} ${options.rootMarginLeft}`,
root,
threshold: options.threshold,
};
}

function calcAuto(container: HTMLElement, margin: string, x: boolean) {
container = container || document.documentElement;
const marginValue = parseInt(margin);
if (isNaN(marginValue)) {
return 0;
}

var clientValue = x ? container.clientWidth : container.clientHeight;

return Math.abs(marginValue) - clientValue;
}

export { observe, unobserve, observeSelector, unobserveSelector };
2 changes: 2 additions & 0 deletions src/Component/BlazorComponent/JSInterop/JsInteropConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public static class JsInteropConstants

public static string ScrollTo => $"{JsInteropFuncNamePrefix}scrollTo";

public static string ScrollToTarget => $"{JsInteropFuncNamePrefix}scrollToTarget";

public static string ScrollIntoView => $"{JsInteropFuncNamePrefix}scrollIntoView";

public static string ScrollToElement => $"{JsInteropFuncNamePrefix}scrollToElement";
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

0 comments on commit 3e757e2

Please sign in to comment.