docs(core): add scroll_25, scroll_50, scroll_75, and scroll_90 events to track engagement (#27461)
This PR adds events to track engagement in our docs. Since we use a scrollable `<div>` in our docs, the normal `scroll` events in GA do not work. A new `<ScrollableContent>` component is added that will do two things: - Send `scroll_25`, `scroll_50`, `scroll_75`, and `scroll_90` events whenever the user scrolls to 25%, 50%, 75%, of 90% of the content - Optionally reset scroll top to zero whenever router changes (existing behavior) All of the places where we have content in a scrollable `<div>` is replaced with `<ScrollableContent>`. Note: 90% means user has reached the bottom, since it's not usually possible to get to 100%.
This commit is contained in:
parent
b699207070
commit
9dca7c7025
@ -4,13 +4,12 @@ import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document';
|
||||
import { MenuItem } from '@nx/nx-dev/models-menu';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticPaths, GetStaticProps } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../lib/menus.api';
|
||||
import { useNavToggle } from '../lib/navigation-toggle.effect';
|
||||
import { nxDocumentationApi } from '../lib/nx.api';
|
||||
import { tagsApi } from '../lib/tags.api';
|
||||
import { fetchGithubStarCount } from '../lib/githubStars.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function NxDocumentation({
|
||||
document,
|
||||
@ -23,25 +22,7 @@ export default function NxDocumentation({
|
||||
relatedDocuments: RelatedDocument[];
|
||||
widgetData: { githubStarsCount: number };
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const menuWithSections = {
|
||||
sections: [getBasicNxSection(menu)],
|
||||
@ -62,18 +43,13 @@ export default function NxDocumentation({
|
||||
toggleNav={toggleNav}
|
||||
navIsOpen={navIsOpen}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<DocViewer
|
||||
document={document}
|
||||
relatedDocuments={relatedDocuments}
|
||||
widgetData={widgetData}
|
||||
/>
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -4,13 +4,12 @@ import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document';
|
||||
import { Menu, MenuItem } from '@nx/nx-dev/models-menu';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticPaths, GetStaticProps } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { ciApi } from '../../lib/ci.api';
|
||||
import { menusApi } from '../../lib/menus.api';
|
||||
import { useNavToggle } from '../../lib/navigation-toggle.effect';
|
||||
import { tagsApi } from '../../lib/tags.api';
|
||||
import { fetchGithubStarCount } from '../../lib/githubStars.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function Pages({
|
||||
document,
|
||||
@ -23,25 +22,7 @@ export default function Pages({
|
||||
relatedDocuments: RelatedDocument[];
|
||||
widgetData: { githubStarsCount: number };
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
document: ProcessedDocument;
|
||||
@ -70,18 +51,13 @@ export default function Pages({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<DocViewer
|
||||
document={vm.document}
|
||||
relatedDocuments={vm.relatedDocuments}
|
||||
widgetData={widgetData}
|
||||
/>
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -4,13 +4,12 @@ import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document';
|
||||
import { Menu, MenuItem } from '@nx/nx-dev/models-menu';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticProps } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { ciApi } from '../../lib/ci.api';
|
||||
import { menusApi } from '../../lib/menus.api';
|
||||
import { useNavToggle } from '../../lib/navigation-toggle.effect';
|
||||
import { tagsApi } from '../../lib/tags.api';
|
||||
import { fetchGithubStarCount } from '../../lib/githubStars.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function CloudRoot({
|
||||
document,
|
||||
@ -23,25 +22,7 @@ export default function CloudRoot({
|
||||
relatedDocuments: RelatedDocument[];
|
||||
widgetData: { githubStarsCount: number };
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
document: ProcessedDocument;
|
||||
@ -70,18 +51,13 @@ export default function CloudRoot({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<DocViewer
|
||||
document={document}
|
||||
relatedDocuments={vm.relatedDocuments}
|
||||
widgetData={widgetData}
|
||||
/>
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -11,6 +11,7 @@ import { useNavToggle } from '../../lib/navigation-toggle.effect';
|
||||
import { nxPluginsApi } from '../../lib/plugins.api';
|
||||
import { tagsApi } from '../../lib/tags.api';
|
||||
import { fetchGithubStarCount } from '../../lib/githubStars.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function Pages({
|
||||
document,
|
||||
@ -23,25 +24,7 @@ export default function Pages({
|
||||
relatedDocuments: RelatedDocument[];
|
||||
widgetData: { githubStarsCount: number };
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
document: ProcessedDocument;
|
||||
@ -70,18 +53,13 @@ export default function Pages({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<DocViewer
|
||||
document={vm.document}
|
||||
relatedDocuments={vm.relatedDocuments}
|
||||
widgetData={widgetData}
|
||||
/>
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -4,13 +4,12 @@ import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document';
|
||||
import { Menu, MenuItem } from '@nx/nx-dev/models-menu';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticProps } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../lib/menus.api';
|
||||
import { useNavToggle } from '../../lib/navigation-toggle.effect';
|
||||
import { nxPluginsApi } from '../../lib/plugins.api';
|
||||
import { tagsApi } from '../../lib/tags.api';
|
||||
import { fetchGithubStarCount } from '../../lib/githubStars.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function PluginsRoot({
|
||||
document,
|
||||
@ -23,25 +22,7 @@ export default function PluginsRoot({
|
||||
relatedDocuments: RelatedDocument[];
|
||||
widgetData: { githubStarsCount: number };
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
document: ProcessedDocument;
|
||||
@ -70,18 +51,13 @@ export default function PluginsRoot({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<DocViewer
|
||||
document={document}
|
||||
relatedDocuments={vm.relatedDocuments}
|
||||
widgetData={widgetData}
|
||||
/>
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -7,13 +7,12 @@ import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticPaths } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { nxPackagesApi } from '../../../../lib/packages.api';
|
||||
import { tagsApi } from '../../../../lib/tags.api';
|
||||
import { fetchGithubStarCount } from '../../../../lib/githubStars.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function PackageDocument({
|
||||
document,
|
||||
@ -27,25 +26,7 @@ export default function PackageDocument({
|
||||
relatedDocuments: RelatedDocument[];
|
||||
widgetData: { githubStarsCount: number };
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
document: ProcessedDocument;
|
||||
@ -77,18 +58,13 @@ export default function PackageDocument({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<DocViewer
|
||||
document={vm.document}
|
||||
relatedDocuments={vm.relatedDocuments}
|
||||
widgetData={widgetData}
|
||||
/>
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -4,12 +4,11 @@ import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticPaths } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { PackageSchemaSubList } from '@nx/nx-dev/feature-package-schema-viewer/src/lib/package-schema-sub-list';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { nxPackagesApi } from '../../../../lib/packages.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function DocumentsIndex({
|
||||
menu,
|
||||
@ -18,25 +17,7 @@ export default function DocumentsIndex({
|
||||
menu: MenuItem[];
|
||||
pkg: ProcessedPackageMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
|
||||
menu: {
|
||||
@ -69,14 +50,9 @@ export default function DocumentsIndex({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaSubList pkg={vm.package} type={'document'} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
@ -92,6 +68,7 @@ export const getStaticPaths: GetStaticPaths = () => {
|
||||
fallback: 'blocking',
|
||||
};
|
||||
};
|
||||
|
||||
export async function getStaticProps({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@ -8,11 +8,10 @@ import {
|
||||
} from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticPaths } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { nxPackagesApi } from '../../../../lib/packages.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function PackageExecutor({
|
||||
menu,
|
||||
@ -23,25 +22,7 @@ export default function PackageExecutor({
|
||||
pkg: ProcessedPackageMetadata;
|
||||
schema: SchemaMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
menu: Menu;
|
||||
@ -79,14 +60,9 @@ export default function PackageExecutor({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaViewer pkg={vm.package} schema={vm.schema} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
@ -124,6 +100,7 @@ function getData(
|
||||
menu: menusApi.getMenu('nx-api', 'nx-api'),
|
||||
};
|
||||
}
|
||||
|
||||
export async function getStaticProps({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@ -4,12 +4,11 @@ import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticPaths } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { PackageSchemaSubList } from '@nx/nx-dev/feature-package-schema-viewer/src/lib/package-schema-sub-list';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { nxPackagesApi } from '../../../../lib/packages.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function ExecutorsIndex({
|
||||
menu,
|
||||
@ -18,25 +17,7 @@ export default function ExecutorsIndex({
|
||||
menu: MenuItem[];
|
||||
pkg: ProcessedPackageMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
|
||||
menu: {
|
||||
@ -69,14 +50,9 @@ export default function ExecutorsIndex({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaSubList pkg={vm.package} type={'executor'} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
@ -92,6 +68,7 @@ export const getStaticPaths: GetStaticPaths = () => {
|
||||
fallback: 'blocking',
|
||||
};
|
||||
};
|
||||
|
||||
export async function getStaticProps({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@ -8,11 +8,10 @@ import {
|
||||
} from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticPaths } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { nxPackagesApi } from '../../../../lib/packages.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function PackageGenerator({
|
||||
menu,
|
||||
@ -23,26 +22,7 @@ export default function PackageGenerator({
|
||||
pkg: ProcessedPackageMetadata;
|
||||
schema: SchemaMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
menu: Menu;
|
||||
package: ProcessedPackageMetadata;
|
||||
@ -79,14 +59,9 @@ export default function PackageGenerator({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaViewer pkg={vm.package} schema={vm.schema} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
@ -124,6 +99,7 @@ function getData(
|
||||
menu: menusApi.getMenu('nx-api', 'nx-api'),
|
||||
};
|
||||
}
|
||||
|
||||
export async function getStaticProps({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@ -4,12 +4,11 @@ import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticPaths } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { PackageSchemaSubList } from '@nx/nx-dev/feature-package-schema-viewer/src/lib/package-schema-sub-list';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { nxPackagesApi } from '../../../../lib/packages.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function GeneratorsIndex({
|
||||
menu,
|
||||
@ -18,25 +17,7 @@ export default function GeneratorsIndex({
|
||||
menu: MenuItem[];
|
||||
pkg: ProcessedPackageMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
|
||||
menu: {
|
||||
@ -69,14 +50,9 @@ export default function GeneratorsIndex({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaSubList pkg={vm.package} type={'generator'} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
@ -92,6 +68,7 @@ export const getStaticPaths: GetStaticPaths = () => {
|
||||
fallback: 'blocking',
|
||||
};
|
||||
};
|
||||
|
||||
export async function getStaticProps({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@ -6,12 +6,11 @@ import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { GetStaticPaths } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../lib/navigation-toggle.effect';
|
||||
import { nxPackagesApi } from '../../../lib/packages.api';
|
||||
import { tagsApi } from '../../../lib/tags.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function Package({
|
||||
overview,
|
||||
@ -22,25 +21,7 @@ export default function Package({
|
||||
overview: string;
|
||||
pkg: ProcessedPackageMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
|
||||
menu: {
|
||||
@ -73,14 +54,9 @@ export default function Package({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaList pkg={vm.package} overview={overview} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
@ -129,6 +105,7 @@ function getData(packageName: string): {
|
||||
pkg,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getStaticProps({ params }: { params: { name: string } }) {
|
||||
try {
|
||||
return { props: getData(params.name) };
|
||||
|
||||
@ -20,6 +20,7 @@ import { useMemo } from 'react';
|
||||
import { menusApi } from '../../lib/menus.api';
|
||||
import { useNavToggle } from '../../lib/navigation-toggle.effect';
|
||||
import { nxPackagesApi } from '../../lib/packages.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function Packages({
|
||||
packages,
|
||||
@ -97,11 +98,7 @@ export default function Packages({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent>
|
||||
<div className="mx-auto w-full grow items-stretch px-4 sm:px-6 lg:px-8 2xl:max-w-6xl">
|
||||
<div id="content-wrapper" className="w-full flex-auto flex-col">
|
||||
<div className="mb-6 pt-8">
|
||||
@ -152,7 +149,7 @@ export default function Packages({
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -3,12 +3,11 @@ import { sortCorePackagesFirst } from '@nx/nx-dev/data-access-packages';
|
||||
import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { PackageSchemaSubList } from '@nx/nx-dev/feature-package-schema-viewer/src/lib/package-schema-sub-list';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function DocumentsIndex({
|
||||
menu,
|
||||
@ -17,25 +16,7 @@ export default function DocumentsIndex({
|
||||
menu: MenuItem[];
|
||||
pkg: ProcessedPackageMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
|
||||
menu: {
|
||||
@ -68,14 +49,9 @@ export default function DocumentsIndex({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaSubList pkg={vm.package} type={'document'} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -5,13 +5,12 @@ import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document';
|
||||
import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { content } from '../../../../lib/rspack/content/overview';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { fetchGithubStarCount } from '../../../../lib/githubStars.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function Overview({
|
||||
document,
|
||||
@ -25,25 +24,7 @@ export default function Overview({
|
||||
relatedDocuments: RelatedDocument[];
|
||||
widgetData: { githubStarsCount: number };
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
document: ProcessedDocument;
|
||||
@ -75,18 +56,13 @@ export default function Overview({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<DocViewer
|
||||
document={vm.document}
|
||||
relatedDocuments={vm.relatedDocuments}
|
||||
widgetData={widgetData}
|
||||
/>
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -5,13 +5,12 @@ import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document';
|
||||
import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { content } from '../../../../lib/rspack/content/rspack-config-setup';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { fetchGithubStarCount } from '../../../../lib/githubStars.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function RspackConfigSetup({
|
||||
document,
|
||||
@ -25,25 +24,7 @@ export default function RspackConfigSetup({
|
||||
relatedDocuments: RelatedDocument[];
|
||||
widgetData: { githubStarsCount: number };
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
document: ProcessedDocument;
|
||||
@ -75,18 +56,13 @@ export default function RspackConfigSetup({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<DocViewer
|
||||
document={vm.document}
|
||||
relatedDocuments={vm.relatedDocuments}
|
||||
widgetData={widgetData}
|
||||
/>
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -5,13 +5,12 @@ import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document';
|
||||
import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { content } from '../../../../lib/rspack/content/rspack-plugin';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { fetchGithubStarCount } from '../../../../lib/githubStars.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function RspackPlugins({
|
||||
document,
|
||||
@ -25,25 +24,7 @@ export default function RspackPlugins({
|
||||
relatedDocuments: RelatedDocument[];
|
||||
widgetData: { githubStarsCount: number };
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
document: ProcessedDocument;
|
||||
@ -75,18 +56,13 @@ export default function RspackPlugins({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<DocViewer
|
||||
document={vm.document}
|
||||
relatedDocuments={vm.relatedDocuments}
|
||||
widgetData={widgetData}
|
||||
/>
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -7,12 +7,11 @@ import {
|
||||
SchemaMetadata,
|
||||
} from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { schema } from '../../../../lib/rspack/schema/executors/dev-server';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function DevServerExecutor({
|
||||
menu,
|
||||
@ -23,25 +22,7 @@ export default function DevServerExecutor({
|
||||
pkg: ProcessedPackageMetadata;
|
||||
schema: SchemaMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
menu: Menu;
|
||||
@ -79,14 +60,9 @@ export default function DevServerExecutor({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaViewer pkg={vm.package} schema={vm.schema} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -3,12 +3,11 @@ import { sortCorePackagesFirst } from '@nx/nx-dev/data-access-packages';
|
||||
import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { PackageSchemaSubList } from '@nx/nx-dev/feature-package-schema-viewer/src/lib/package-schema-sub-list';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function ExecutorsIndex({
|
||||
menu,
|
||||
@ -17,25 +16,7 @@ export default function ExecutorsIndex({
|
||||
menu: MenuItem[];
|
||||
pkg: ProcessedPackageMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
|
||||
menu: {
|
||||
@ -68,14 +49,9 @@ export default function ExecutorsIndex({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaSubList pkg={vm.package} type={'executor'} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -7,12 +7,11 @@ import {
|
||||
SchemaMetadata,
|
||||
} from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { schema } from '../../../../lib/rspack/schema/executors/rspack';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function RspackExecutor({
|
||||
menu,
|
||||
@ -23,25 +22,7 @@ export default function RspackExecutor({
|
||||
pkg: ProcessedPackageMetadata;
|
||||
schema: SchemaMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
menu: Menu;
|
||||
@ -79,14 +60,9 @@ export default function RspackExecutor({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaViewer pkg={vm.package} schema={vm.schema} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -7,12 +7,11 @@ import {
|
||||
SchemaMetadata,
|
||||
} from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { schema } from '../../../../lib/rspack/schema/generators/application';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function ApplicationGenerator({
|
||||
menu,
|
||||
@ -23,25 +22,7 @@ export default function ApplicationGenerator({
|
||||
pkg: ProcessedPackageMetadata;
|
||||
schema: SchemaMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
menu: Menu;
|
||||
@ -79,14 +60,9 @@ export default function ApplicationGenerator({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaViewer pkg={vm.package} schema={vm.schema} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -7,12 +7,11 @@ import {
|
||||
SchemaMetadata,
|
||||
} from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { schema } from '../../../../lib/rspack/schema/generators/configuration';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function ConfigurationGenerator({
|
||||
menu,
|
||||
@ -23,25 +22,7 @@ export default function ConfigurationGenerator({
|
||||
pkg: ProcessedPackageMetadata;
|
||||
schema: SchemaMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
menu: Menu;
|
||||
@ -79,14 +60,9 @@ export default function ConfigurationGenerator({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaViewer pkg={vm.package} schema={vm.schema} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -3,12 +3,11 @@ import { sortCorePackagesFirst } from '@nx/nx-dev/data-access-packages';
|
||||
import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { PackageSchemaSubList } from '@nx/nx-dev/feature-package-schema-viewer/src/lib/package-schema-sub-list';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function GeneratorsIndex({
|
||||
menu,
|
||||
@ -17,25 +16,7 @@ export default function GeneratorsIndex({
|
||||
menu: MenuItem[];
|
||||
pkg: ProcessedPackageMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
|
||||
menu: {
|
||||
@ -68,14 +49,9 @@ export default function GeneratorsIndex({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaSubList pkg={vm.package} type={'generator'} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -7,12 +7,11 @@ import {
|
||||
SchemaMetadata,
|
||||
} from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
|
||||
import { schema } from '../../../../lib/rspack/schema/generators/init';
|
||||
import { pkg } from '../../../../lib/rspack/pkg';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function InitGenerator({
|
||||
menu,
|
||||
@ -23,25 +22,7 @@ export default function InitGenerator({
|
||||
pkg: ProcessedPackageMetadata;
|
||||
schema: SchemaMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: {
|
||||
menu: Menu;
|
||||
@ -79,14 +60,9 @@ export default function InitGenerator({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaViewer pkg={vm.package} schema={vm.schema} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -4,12 +4,11 @@ import { sortCorePackagesFirst } from '@nx/nx-dev/data-access-packages';
|
||||
import { Menu, MenuItem, MenuSection } from '@nx/nx-dev/models-menu';
|
||||
import { ProcessedPackageMetadata } from '@nx/nx-dev/models-package';
|
||||
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { menusApi } from '../../../lib/menus.api';
|
||||
import { useNavToggle } from '../../../lib/navigation-toggle.effect';
|
||||
import { content } from '../../../lib/rspack/content/overview';
|
||||
import { pkg } from '../../../lib/rspack/pkg';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
export default function RspackIndex({
|
||||
overview,
|
||||
@ -20,25 +19,7 @@ export default function RspackIndex({
|
||||
overview: string;
|
||||
pkg: ProcessedPackageMetadata;
|
||||
}): JSX.Element {
|
||||
const router = useRouter();
|
||||
const { toggleNav, navIsOpen } = useNavToggle();
|
||||
const wrapperElement = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement) return;
|
||||
|
||||
(wrapperElement as any).current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [router, wrapperElement]);
|
||||
|
||||
const vm: { menu: Menu; package: ProcessedPackageMetadata } = {
|
||||
menu: {
|
||||
@ -71,14 +52,9 @@ export default function RspackIndex({
|
||||
navIsOpen={navIsOpen}
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent resetScrollOnNavigation={true}>
|
||||
<PackageSchemaList pkg={vm.package} overview={overview} />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -12,6 +12,7 @@ import { useRouter } from 'next/router';
|
||||
import { menusApi } from '../lib/menus.api';
|
||||
import { useNavToggle } from '../lib/navigation-toggle.effect';
|
||||
import { nxPackagesApi } from '../lib/packages.api';
|
||||
import { ScrollableContent } from '@nx/ui-scrollable-content';
|
||||
|
||||
declare const fetch: any;
|
||||
let qualityIndicators = require('./quality-indicators.json');
|
||||
@ -112,11 +113,7 @@ export default function Browse(props: BrowseProps): JSX.Element {
|
||||
toggleNav={toggleNav}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
>
|
||||
<ScrollableContent>
|
||||
<div className="mx-auto w-full grow items-stretch px-4 sm:px-6 lg:px-8 2xl:max-w-6xl">
|
||||
<div id="content-wrapper" className="w-full flex-auto flex-col">
|
||||
<div className="mb-6 pt-8">
|
||||
@ -141,7 +138,7 @@ export default function Browse(props: BrowseProps): JSX.Element {
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
</ScrollableContent>
|
||||
</main>
|
||||
</div>
|
||||
</>
|
||||
|
||||
12
nx-dev/ui-scrollable-content/.babelrc
Normal file
12
nx-dev/ui-scrollable-content/.babelrc
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@nx/react/babel",
|
||||
{
|
||||
"runtime": "automatic",
|
||||
"useBuiltIns": "usage"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
||||
18
nx-dev/ui-scrollable-content/.eslintrc.json
Normal file
18
nx-dev/ui-scrollable-content/.eslintrc.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
7
nx-dev/ui-scrollable-content/README.md
Normal file
7
nx-dev/ui-scrollable-content/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# ui-scrollable-content
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `nx test ui-scrollable-content` to execute the unit tests via [Jest](https://jestjs.io).
|
||||
9
nx-dev/ui-scrollable-content/jest.config.ts
Normal file
9
nx-dev/ui-scrollable-content/jest.config.ts
Normal file
@ -0,0 +1,9 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: 'nx-dev-ui-scrollable-content',
|
||||
transform: {
|
||||
'^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/next/babel'] }],
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: '../../coverage/nx-dev/ui-scrollable-content',
|
||||
};
|
||||
8
nx-dev/ui-scrollable-content/project.json
Normal file
8
nx-dev/ui-scrollable-content/project.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "nx-dev-ui-scrollable-content",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "nx-dev/ui-scrollable-content/src",
|
||||
"projectType": "library",
|
||||
"tags": ["scope:nx-dev", "type:ui"],
|
||||
"targets": {}
|
||||
}
|
||||
1
nx-dev/ui-scrollable-content/src/index.ts
Normal file
1
nx-dev/ui-scrollable-content/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './lib/scrollable-content';
|
||||
84
nx-dev/ui-scrollable-content/src/lib/scrollable-content.tsx
Normal file
84
nx-dev/ui-scrollable-content/src/lib/scrollable-content.tsx
Normal file
@ -0,0 +1,84 @@
|
||||
import type { JSX, ReactNode, UIEvent } from 'react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { sendCustomEvent } from '@nx/nx-dev/feature-analytics';
|
||||
|
||||
interface ScrollViewProps {
|
||||
children?: ReactNode;
|
||||
resetScrollOnNavigation?: boolean;
|
||||
}
|
||||
|
||||
// Takes in a percentage like 0.33 and rounds to the nearest 0, 25%, 50%, 75%, 90% bucket.
|
||||
function getScrollDepth(pct: number): 0 | 25 | 50 | 75 | 90 {
|
||||
// Anything greater than 0.9 is just 90% and counts as reaching the bottom.
|
||||
if (pct >= 0.9) {
|
||||
return 90;
|
||||
}
|
||||
|
||||
// Otherwise, divide into quarters (0, 25, 50, 75).
|
||||
if (pct < 0.25) return 0;
|
||||
if (pct < 0.5) return 25;
|
||||
if (pct < 0.75) return 50;
|
||||
return 75;
|
||||
}
|
||||
|
||||
export function ScrollableContent(props: ScrollViewProps): JSX.Element {
|
||||
const wrapperElement = useRef<HTMLDivElement | null>(null);
|
||||
const router = useRouter();
|
||||
const scrollDepth = useRef(0);
|
||||
const shouldTrackScroll = useRef(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.resetScrollOnNavigation) {
|
||||
scrollDepth.current = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
shouldTrackScroll.current = false;
|
||||
setTimeout(() => {
|
||||
scrollDepth.current = 0;
|
||||
shouldTrackScroll.current = true;
|
||||
}, 1000);
|
||||
|
||||
const handleRouteChange = (url: string) => {
|
||||
if (url.includes('#')) return;
|
||||
if (!wrapperElement.current) return;
|
||||
|
||||
wrapperElement.current.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
};
|
||||
|
||||
router.events.on('routeChangeComplete', handleRouteChange);
|
||||
return () => router.events.off('routeChangeComplete', handleRouteChange);
|
||||
}, [props.resetScrollOnNavigation, router, wrapperElement]);
|
||||
|
||||
const handleScroll = (evt: UIEvent<HTMLDivElement>) => {
|
||||
if (!shouldTrackScroll.current) return;
|
||||
const el = evt.currentTarget;
|
||||
const { scrollHeight, scrollTop, offsetHeight } = el;
|
||||
const depth = getScrollDepth((scrollTop + offsetHeight) / scrollHeight);
|
||||
// Only track changes that are greater than the previous scroll depth.
|
||||
// If a user already viewed 90% of the page we don't need to know they went back to 50%.
|
||||
if (depth > scrollDepth.current) {
|
||||
scrollDepth.current = depth;
|
||||
sendCustomEvent(`scroll_${depth}`, 'scroll', router.asPath);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={wrapperElement}
|
||||
id="wrapper"
|
||||
data-testid="wrapper"
|
||||
className="relative flex flex-grow flex-col items-stretch justify-start overflow-y-scroll"
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ScrollableContent;
|
||||
15
nx-dev/ui-scrollable-content/src/lib/scrollable.util.spec.ts
Normal file
15
nx-dev/ui-scrollable-content/src/lib/scrollable.util.spec.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { getScrollDepth } from './scrollable.util';
|
||||
|
||||
describe('getScrollDepth', () => {
|
||||
it('should return in buckets of 25, 50, 75, and 90 percentages', () => {
|
||||
expect(getScrollDepth(0)).toEqual(0);
|
||||
expect(getScrollDepth(0.24)).toEqual(0);
|
||||
expect(getScrollDepth(0.25)).toEqual(25);
|
||||
expect(getScrollDepth(0.49)).toEqual(25);
|
||||
expect(getScrollDepth(0.5)).toEqual(50);
|
||||
expect(getScrollDepth(0.74)).toEqual(50);
|
||||
expect(getScrollDepth(0.75)).toEqual(75);
|
||||
expect(getScrollDepth(0.9)).toEqual(90);
|
||||
expect(getScrollDepth(1)).toEqual(90);
|
||||
});
|
||||
});
|
||||
15
nx-dev/ui-scrollable-content/src/lib/scrollable.util.ts
Normal file
15
nx-dev/ui-scrollable-content/src/lib/scrollable.util.ts
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Takes in a percentage like 0.33 and rounds to the nearest 0, 25%, 50%, 75%, 90% bucket.
|
||||
*/
|
||||
export function getScrollDepth(pct: number): 0 | 25 | 50 | 75 | 90 {
|
||||
// Anything greater than 0.9 is just 90% and counts as reaching the bottom.
|
||||
if (pct >= 0.9) {
|
||||
return 90;
|
||||
}
|
||||
|
||||
// Otherwise, divide into quarters (0, 25, 50, 75).
|
||||
if (pct < 0.25) return 0;
|
||||
if (pct < 0.5) return 25;
|
||||
if (pct < 0.75) return 50;
|
||||
return 75;
|
||||
}
|
||||
21
nx-dev/ui-scrollable-content/tsconfig.json
Normal file
21
nx-dev/ui-scrollable-content/tsconfig.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"lib": ["dom"]
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
}
|
||||
],
|
||||
"extends": "../../tsconfig.base.json"
|
||||
}
|
||||
23
nx-dev/ui-scrollable-content/tsconfig.lib.json
Normal file
23
nx-dev/ui-scrollable-content/tsconfig.lib.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": [
|
||||
"node",
|
||||
"@nx/react/typings/cssmodule.d.ts",
|
||||
"@nx/react/typings/image.d.ts"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"jest.config.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.jsx",
|
||||
"src/**/*.test.jsx"
|
||||
],
|
||||
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
|
||||
}
|
||||
@ -130,6 +130,9 @@
|
||||
"@nx/storybook": ["packages/storybook"],
|
||||
"@nx/storybook/*": ["packages/storybook/*"],
|
||||
"@nx/typedoc-theme": ["typedoc-theme/src/index.ts"],
|
||||
"@nx/ui-scrollable-content": [
|
||||
"nx-dev/ui-scrollable-content/src/index.ts"
|
||||
],
|
||||
"@nx/vite": ["packages/vite"],
|
||||
"@nx/vite/*": ["packages/vite/*"],
|
||||
"@nx/vue": ["packages/vue"],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user