Skip to content
This repository has been archived by the owner on Nov 5, 2023. It is now read-only.

Commit

Permalink
feat: support running inside a native web component
Browse files Browse the repository at this point in the history
  • Loading branch information
rocwang committed Oct 14, 2022
1 parent f0b3cdc commit 5e33290
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 22 deletions.
12 changes: 8 additions & 4 deletions src/Grid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

<template
v-for="internalItem in buffer"
:key="getKey ? getKey(internalItem) : keyPrefix + '.' + internalItem.index"
:key="
getKey ? getKey(internalItem) : keyPrefix + '.' + internalItem.index
"
>
<slot
v-if="internalItem.value === undefined"
Expand Down Expand Up @@ -49,7 +51,7 @@ import {
import {
fromProp,
fromResizeObserver,
fromWindowScroll,
fromScrollParent,
useObservable,
} from "./utilites";
import { InternalItem, PageProvider, pipeline, ScrollAction } from "./pipeline";
Expand Down Expand Up @@ -113,7 +115,9 @@ export default defineComponent({
default: "div",
},
getKey: {
type: Function as PropType<(internalItem: InternalItem) => number | string>,
type: Function as PropType<
(internalItem: InternalItem) => number | string
>,
required: false,
default: undefined,
},
Expand All @@ -139,7 +143,7 @@ export default defineComponent({
// a stream of root elements when it is resized
rootResize$: fromResizeObserver(rootRef, "target"),
// a stream of root elements when scrolling
scroll$: fromWindowScroll(rootRef),
scroll$: fromScrollParent(rootRef),
respectScrollToOnResize$: fromProp(props, "respectScrollToOnResize"),
scrollTo$: fromProp(props, "scrollTo"),
});
Expand Down
58 changes: 40 additions & 18 deletions src/utilites.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {
animationFrameScheduler,
filter,
fromEvent,
fromEventPattern,
map,
mergeAll,
Observable,
pluck,
scheduled,
Subject,
} from "rxjs";
import { Ref, ref, watchEffect } from "vue";
import { onMounted, Ref, ref, watchEffect } from "vue";
import { partial, pipe, unary } from "ramda";
import {
MaybeElementRef,
Expand Down Expand Up @@ -36,25 +36,46 @@ export function fromResizeObserver<T extends keyof ResizeObserverEntry>(
pipe(unary, partial(useResizeObserver, [elRef]))
),
animationFrameScheduler
).pipe(mergeAll(), pluck<ResizeObserverEntry, T>(pluckTarget));
}

export function fromWindowScroll(elRef: MaybeElementRef): Observable<Element> {
return fromEvent(
window,
"scroll",
{
passive: true,
capture: true,
},
() => unrefElement(elRef)
).pipe(
filter<Element | undefined | null, Element>((el): el is Element =>
Boolean(el)
mergeAll(),
map<ResizeObserverEntry, ResizeObserverEntry[T]>(
(entry) => entry[pluckTarget]
)
);
}

export function fromScrollParent(elRef: MaybeElementRef): Observable<Element> {
const scrollSubject = new Subject<Element>();

onMounted(() => {
const el = unrefElement(elRef);

if (el) {
const { vertical, horizontal } = getScrollParents(el);

const scrollParents =
vertical === horizontal ? [vertical] : [vertical, horizontal];

const pushEl = () => scrollSubject.next(el);

scrollParents.forEach((parent) =>
parent.addEventListener("scroll", pushEl, {
passive: true,
capture: true,
})
);

tryOnUnmounted(() =>
scrollParents.forEach((parent) =>
parent.removeEventListener("scroll", pushEl)
)
);
}
});

return scrollSubject;
}

export function useObservable<H>(observable: Observable<H>): Readonly<Ref<H>> {
const valueRef = ref<H>();
const subscription = observable.subscribe((val) => (valueRef.value = val));
Expand Down Expand Up @@ -92,7 +113,8 @@ export function getScrollParents(

for (
let parent: Element | null = element;
(parent = parent.parentElement);
// parent.assignedSlot.parentElement find the correct parent if the grid is inside a native web component
(parent = parent.assignedSlot?.parentElement ?? parent.parentElement);

) {
const parentStyle = getComputedStyle(parent);
Expand Down

0 comments on commit 5e33290

Please sign in to comment.