From 5f302430720ab1859b8ccb23a889eb08bf7f1b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Baranx?= Date: Tue, 27 Feb 2024 07:23:45 +0700 Subject: [PATCH] [feat] add permalinks on libfuncs --- components/LibFuncTable/Filters.tsx | 12 ---- components/LibFuncTable/index.tsx | 107 ++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 17 deletions(-) diff --git a/components/LibFuncTable/Filters.tsx b/components/LibFuncTable/Filters.tsx index 541be7d..05b514b 100644 --- a/components/LibFuncTable/Filters.tsx +++ b/components/LibFuncTable/Filters.tsx @@ -42,13 +42,6 @@ const Filters = ({ onSetFilter }: Props) => { setSearchFilter(option) } - const handleAltK = (event: KeyboardEvent) => { - if (event.altKey && event.key.toLowerCase() === 'k') { - inputRef.current?.focus() - inputRef.current?.value && inputRef.current.select() - } - } - // Change filter and search opcode according to query param useEffect(() => { const query = router.query @@ -61,10 +54,6 @@ const Filters = ({ onSetFilter }: Props) => { router.push(router) } - // Register and clean up Alt+K event listener - window.addEventListener('keydown', handleAltK) - return () => window.removeEventListener('keydown', handleAltK) - // eslint-disable-next-line react-hooks/exhaustive-deps }, [router.isReady]) @@ -88,7 +77,6 @@ const Filters = ({ onSetFilter }: Props) => { { setSearchKeyword(e.target.value) diff --git a/components/LibFuncTable/index.tsx b/components/LibFuncTable/index.tsx index 42a9d2c..df40e56 100644 --- a/components/LibFuncTable/index.tsx +++ b/components/LibFuncTable/index.tsx @@ -1,12 +1,19 @@ -import { useMemo, Fragment } from 'react' +import { useMemo, Fragment, useRef, useState, useEffect } from 'react' -import { RiArrowUpSLine, RiArrowDownSLine } from '@remixicon/react' +import { + RiCheckLine, + RiLinksLine, + RiArrowUpSLine, + RiArrowDownSLine, +} from '@remixicon/react' import cn from 'classnames' +import { useRouter } from 'next/router' import { useTable, useExpanded, useFilters, Row, + Cell, UseExpandedRowProps, } from 'react-table' import { ILibFuncDocs, ILibFuncDoc } from 'types' @@ -18,6 +25,8 @@ import DocRowDetail from './DocRowDetail' import Filters from './Filters' const LibFuncTable = ({ docs }: { docs: ILibFuncDocs }) => { + const router = useRouter() + const data = useMemo(() => docs, [docs]) const columns = useMemo(() => columnDefinition, []) @@ -39,6 +48,55 @@ const LibFuncTable = ({ docs }: { docs: ILibFuncDocs }) => { setFilter, } = table + const rowRefs = useRef([]) + const [focusedLibFuncIndex, setFocusedLibFuncIndex] = useState< + number | null + >() + + const [clickedPermalinks, setClickedPermalinks] = useState<{ + [key: string]: boolean + }>(docs.reduce((state, current) => ({ ...state, [current.name]: false }), {})) + + const handlePermalink = (libFuncName: string) => { + const pageUrl = `${window.location.origin}${window.location.pathname}` + const permalink = `${pageUrl}#${libFuncName}` + + navigator.clipboard.writeText(permalink) + + // make the permalinks temporary "clicked" to show a specific icon/message + setClickedPermalinks((previous) => ({ + ...previous, + [libFuncName]: true, + })) + setTimeout( + () => + setClickedPermalinks((previous) => ({ + ...previous, + [libFuncName]: false, + })), + 1000, + ) + } + + // Focus and expand anchored reference + useEffect(() => { + if (docs && rowRefs?.current) { + const libFuncIndex = docs.findIndex((item) => { + const re = new RegExp(`#${item.name}`, 'gi') + return router.asPath.match(re) + }) + + if (libFuncIndex >= 0) { + setFocusedLibFuncIndex(libFuncIndex) + setTimeout(() => { + if (rowRefs.current[libFuncIndex]) { + rowRefs.current[libFuncIndex].scrollIntoView({ behavior: 'smooth' }) + } + }, 300) + } + } + }, [docs, router.asPath]) + const renderExpandButton = () => { return (
@@ -98,6 +156,35 @@ const LibFuncTable = ({ docs }: { docs: ILibFuncDocs }) => { ) } + + const renderPermalinkCell = ( + listFuncName: string, + cell: Cell, + ) => { + return ( +
+ {clickedPermalinks[listFuncName] ? ( + <> + + copied ! + + ) : ( + <> + { + handlePermalink(listFuncName) + e.stopPropagation() + }} + /> + {cell.render('Cell')} + + )} +
+ ) + } + const renderBody = () => { return ( @@ -106,12 +193,20 @@ const LibFuncTable = ({ docs }: { docs: ILibFuncDocs }) => { const expandedRow = row as Row & UseExpandedRowProps + const rowId = parseInt(row.id) const rowObject = row.original - const isExpanded = expandedRow.isExpanded + const isExpanded = + expandedRow.isExpanded || focusedLibFuncIndex === rowId return ( { + if (el) { + rowRefs.current[row.index] = el + } + }} className={cn('border-t cursor-pointer', { 'border-gray-200 dark:border-black-500 hover:bg-gray-100 dark:hover:bg-black-600': !isExpanded, @@ -122,14 +217,16 @@ const LibFuncTable = ({ docs }: { docs: ILibFuncDocs }) => { onClick={() => row.toggleRowExpanded()} style={{ scrollMarginTop: '96px' }} > - {row.cells.map((cell) => ( + {row.cells.map((cell, cellIndex) => ( - {cell.render('Cell')} + {cellIndex === 0 + ? renderPermalinkCell(rowObject.name, cell) + : cell.render('Cell')} ))}