From 0fbe05dc0eb1baced8c785fdf26c430470c419df Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Thu, 31 Oct 2024 17:09:12 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.json | 1 - .vscode/launch.json | 34 ++++++++++ examples/full/package.json | 2 +- examples/minimal/package.json | 2 +- packages/react-notion-x/src/block.tsx | 18 ++++- .../src/components/asset-wrapper.tsx | 7 +- .../react-notion-x/src/components/asset.tsx | 8 ++- .../react-notion-x/src/components/audio.tsx | 7 +- .../src/components/checkbox.tsx | 6 +- .../react-notion-x/src/components/eoi.tsx | 8 ++- .../react-notion-x/src/components/file.tsx | 7 +- .../src/components/google-drive.tsx | 7 +- .../src/components/graceful-image.tsx | 2 +- .../react-notion-x/src/components/header.tsx | 21 ++++-- .../src/components/lazy-image.tsx | 20 +++--- .../src/components/lite-youtube-embed.tsx | 26 ++++---- .../src/components/mention-preview-card.tsx | 10 ++- .../src/components/page-aside.tsx | 20 +++--- .../src/components/page-icon.tsx | 16 ++--- .../src/components/page-title.tsx | 11 +++- .../src/components/sync-pointer-block.tsx | 7 +- .../react-notion-x/src/components/text.tsx | 9 ++- packages/react-notion-x/src/context.tsx | 47 ++++++++------ .../src/icons/chevron-down-icon.tsx | 2 +- .../react-notion-x/src/icons/clear-icon.tsx | 2 +- .../src/icons/collection-view-icon.tsx | 6 +- .../src/icons/default-page-icon.tsx | 2 +- .../react-notion-x/src/icons/empty-icon.tsx | 2 +- .../react-notion-x/src/icons/file-icon.tsx | 2 +- .../react-notion-x/src/icons/link-icon.tsx | 2 +- .../react-notion-x/src/icons/loading-icon.tsx | 2 +- .../src/icons/property-icon.tsx | 6 +- .../react-notion-x/src/icons/search-icon.tsx | 2 +- packages/react-notion-x/src/next.tsx | 7 +- packages/react-notion-x/src/renderer.tsx | 65 ++++++++++--------- .../react-notion-x/src/third-party/code.tsx | 8 ++- .../src/third-party/collection-card.tsx | 4 +- .../third-party/collection-column-title.tsx | 6 +- .../src/third-party/collection-group.tsx | 4 +- .../src/third-party/collection-row.tsx | 8 ++- .../src/third-party/collection-view-board.tsx | 4 +- .../third-party/collection-view-gallery.tsx | 4 +- .../src/third-party/collection-view-list.tsx | 4 +- .../src/third-party/collection-view-table.tsx | 4 +- .../src/third-party/collection-view.tsx | 2 +- .../src/third-party/collection.tsx | 32 ++++++--- .../src/third-party/equation.tsx | 10 ++- .../react-notion-x/src/third-party/pdf.tsx | 2 +- .../src/third-party/property.tsx | 5 +- 49 files changed, 315 insertions(+), 178 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.eslintrc.json b/.eslintrc.json index 0fb9bee16..d6823ef9f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,7 +2,6 @@ "root": true, "extends": ["@fisch0920/eslint-config"], "rules": { - "react/function-component-definition": "off", "react/prop-types": "off", "unicorn/no-array-reduce": "off", "unicorn/filename-case": "off", diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..e3c4dc61d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,34 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Next.js: debug server-side", + "type": "node-terminal", + "request": "launch", + "command": "./node_modules/.bin/next dev", + "cwd": "${workspaceFolder}/examples/minimal" + }, + { + "name": "Next.js: debug client-side", + "type": "chrome", + "request": "launch", + "url": "http://localhost:3000" + }, + { + "name": "Next.js: debug full stack", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/examples/minimal/node_modules/.bin/next", + "cwd": "${workspaceFolder}/examples/minimal", + "runtimeArgs": ["--inspect"], + "skipFiles": ["/**"], + "serverReadyAction": { + "action": "debugWithEdge", + "killOnServerStop": true, + "pattern": "- Local:.+(https?://.+)", + "uriFormat": "%s", + "webRoot": "${workspaceFolder}/examples/minimal" + } + } + ] +} diff --git a/examples/full/package.json b/examples/full/package.json index 557a11ccd..fbecaa8f8 100644 --- a/examples/full/package.json +++ b/examples/full/package.json @@ -2,7 +2,7 @@ "name": "notion-x-example-full", "version": "6.16.2", "private": true, - "type": "commonjs", + "type": "module", "scripts": { "dev": "next dev", "build": "next build", diff --git a/examples/minimal/package.json b/examples/minimal/package.json index a464da3d4..500e85497 100644 --- a/examples/minimal/package.json +++ b/examples/minimal/package.json @@ -2,7 +2,7 @@ "name": "notion-x-example-minimal", "version": "6.16.1", "private": true, - "type": "commonjs", + "type": "module", "scripts": { "dev": "next dev", "build": "next build", diff --git a/packages/react-notion-x/src/block.tsx b/packages/react-notion-x/src/block.tsx index 02023cd78..938e0d8e9 100644 --- a/packages/react-notion-x/src/block.tsx +++ b/packages/react-notion-x/src/block.tsx @@ -53,7 +53,13 @@ const tocIndentLevelCache: { const pageCoverStyleCache: Record = {} -export const Block: React.FC = (props: BlockProps) => { +export function Block(props: BlockProps) { + console.log('Block', { + id: props.block.id, + type: props.block.type, + level: props.level + }) + const ctx = useNotionContext() const { components, @@ -148,6 +154,16 @@ export const Block: React.FC = (props: BlockProps) => { const hasAside = !!((hasToc || pageAside) && !page_full_width) const hasPageCover = !!(pageCover || page_cover) + console.log({ + disableHeader, + header, + pageCover, + pageHeader, + pageFooter, + footer, + components + }) + return (
= ({ blockId, block }) => { +}) { const value = block as BaseContentBlock const { components, mapPageUrl, rootDomain, zoom } = useNotionContext() diff --git a/packages/react-notion-x/src/components/asset.tsx b/packages/react-notion-x/src/components/asset.tsx index 7c34b9726..7439f7d8d 100644 --- a/packages/react-notion-x/src/components/asset.tsx +++ b/packages/react-notion-x/src/components/asset.tsx @@ -25,11 +25,15 @@ const supportedAssetTypes = new Set([ 'drive' ]) -export const Asset: React.FC<{ +export function Asset({ + block, + zoomable = true, + children +}: { block: BaseContentBlock children: any zoomable?: boolean -}> = ({ block, zoomable = true, children }) => { +}) { const { recordMap, mapImageUrl, components } = useNotionContext() if (!block || !supportedAssetTypes.has(block.type)) { diff --git a/packages/react-notion-x/src/components/audio.tsx b/packages/react-notion-x/src/components/audio.tsx index 5573fa8ec..995f2efbc 100644 --- a/packages/react-notion-x/src/components/audio.tsx +++ b/packages/react-notion-x/src/components/audio.tsx @@ -4,10 +4,13 @@ import { type AudioBlock } from 'notion-types' import { useNotionContext } from '../context' import { cs } from '../utils' -export const Audio: React.FC<{ +export function Audio({ + block, + className +}: { block: AudioBlock className?: string -}> = ({ block, className }) => { +}) { const { recordMap } = useNotionContext() const source = recordMap.signed_urls[block.id] || block.properties?.source?.[0]?.[0] diff --git a/packages/react-notion-x/src/components/checkbox.tsx b/packages/react-notion-x/src/components/checkbox.tsx index 5486a6edf..fd20e0aa5 100644 --- a/packages/react-notion-x/src/components/checkbox.tsx +++ b/packages/react-notion-x/src/components/checkbox.tsx @@ -2,10 +2,12 @@ import type * as React from 'react' import CheckIcon from '../icons/check' -export const Checkbox: React.FC<{ +export function Checkbox({ + isChecked +}: { isChecked: boolean blockId?: string -}> = ({ isChecked }) => { +}) { let content = null if (isChecked) { diff --git a/packages/react-notion-x/src/components/eoi.tsx b/packages/react-notion-x/src/components/eoi.tsx index 0163ca73f..8d54e8934 100644 --- a/packages/react-notion-x/src/components/eoi.tsx +++ b/packages/react-notion-x/src/components/eoi.tsx @@ -7,11 +7,15 @@ import { cs, formatNotionDateTime } from '../utils' import { MentionPreviewCard } from './mention-preview-card' // External Object Instance -export const EOI: React.FC<{ +export function EOI({ + block, + inline, + className +}: { block: Block inline?: boolean className?: string -}> = ({ block, inline, className }) => { +}) { const { components } = useNotionContext() const { original_url, attributes, domain } = block?.format || {} if (!original_url || !attributes) { diff --git a/packages/react-notion-x/src/components/file.tsx b/packages/react-notion-x/src/components/file.tsx index d3c64b378..1d8b88ac6 100644 --- a/packages/react-notion-x/src/components/file.tsx +++ b/packages/react-notion-x/src/components/file.tsx @@ -6,10 +6,13 @@ import { FileIcon } from '../icons/file-icon' import { cs } from '../utils' import { Text } from './text' -export const File: React.FC<{ +export function File({ + block, + className +}: { block: FileBlock className?: string -}> = ({ block, className }) => { +}) { const { components, recordMap } = useNotionContext() const source = recordMap.signed_urls[block.id] || block.properties?.source?.[0]?.[0] diff --git a/packages/react-notion-x/src/components/google-drive.tsx b/packages/react-notion-x/src/components/google-drive.tsx index b5cfca3ea..c9e9316b3 100644 --- a/packages/react-notion-x/src/components/google-drive.tsx +++ b/packages/react-notion-x/src/components/google-drive.tsx @@ -5,10 +5,13 @@ import { useNotionContext } from '../context' import { cs } from '../utils' import { GracefulImage } from './graceful-image' -export const GoogleDrive: React.FC<{ +export function GoogleDrive({ + block, + className +}: { block: GoogleDriveBlock className?: string -}> = ({ block, className }) => { +}) { const { components, mapImageUrl } = useNotionContext() const properties = block.format?.drive_properties if (!properties) return null diff --git a/packages/react-notion-x/src/components/graceful-image.tsx b/packages/react-notion-x/src/components/graceful-image.tsx index 36ec7be5c..768cb232f 100644 --- a/packages/react-notion-x/src/components/graceful-image.tsx +++ b/packages/react-notion-x/src/components/graceful-image.tsx @@ -3,7 +3,7 @@ import { Img, type ImgProps } from 'react-image' import { isBrowser } from '../utils' -export const GracefulImage = (props: ImgProps) => { +export function GracefulImage(props: ImgProps) { if (isBrowser) { return } else { diff --git a/packages/react-notion-x/src/components/header.tsx b/packages/react-notion-x/src/components/header.tsx index 36b782968..c4c400b87 100644 --- a/packages/react-notion-x/src/components/header.tsx +++ b/packages/react-notion-x/src/components/header.tsx @@ -10,9 +10,11 @@ import { cs } from '../utils' import { PageIcon } from './page-icon' import { SearchDialog } from './search-dialog' -export const Header: React.FC<{ +export function Header({ + block +}: { block: types.CollectionViewPageBlock | types.PageBlock -}> = ({ block }) => { +}) { return (
@@ -23,10 +25,13 @@ export const Header: React.FC<{ ) } -export const Breadcrumbs: React.FC<{ +export function Breadcrumbs({ + block, + rootOnly = false +}: { block: types.Block rootOnly?: boolean -}> = ({ block, rootOnly = false }) => { +}) { const { recordMap, mapPageUrl, components } = useNotionContext() const breadcrumbs = React.useMemo(() => { @@ -81,11 +86,15 @@ export const Breadcrumbs: React.FC<{ ) } -export const Search: React.FC<{ +export function Search({ + block, + search, + title = 'Search' +}: { block: types.Block search?: SearchNotionFn title?: React.ReactNode -}> = ({ block, search, title = 'Search' }) => { +}) { const { searchNotion, rootPageId, isShowingSearch, onHideSearch } = useNotionContext() const onSearchNotion = search || searchNotion diff --git a/packages/react-notion-x/src/components/lazy-image.tsx b/packages/react-notion-x/src/components/lazy-image.tsx index 29a00226d..3e45cdad9 100644 --- a/packages/react-notion-x/src/components/lazy-image.tsx +++ b/packages/react-notion-x/src/components/lazy-image.tsx @@ -8,15 +8,7 @@ import { cs } from '../utils' /** * Progressive, lazy images modeled after Medium's LQIP technique. */ -export const LazyImage: React.FC<{ - src?: string - alt?: string - className?: string - style?: React.CSSProperties - height?: number - zoomable?: boolean - priority?: boolean -}> = ({ +export function LazyImage({ src, alt, className, @@ -25,7 +17,15 @@ export const LazyImage: React.FC<{ priority = false, height, ...rest -}) => { +}: { + src?: string + alt?: string + className?: string + style?: React.CSSProperties + height?: number + zoomable?: boolean + priority?: boolean +}) { const { recordMap, zoom, previewImages, forceCustomImages, components } = useNotionContext() const zoomRef = React.useRef(zoom ? zoom.clone() : null) diff --git a/packages/react-notion-x/src/components/lite-youtube-embed.tsx b/packages/react-notion-x/src/components/lite-youtube-embed.tsx index 1d1bad370..151d72aa8 100644 --- a/packages/react-notion-x/src/components/lite-youtube-embed.tsx +++ b/packages/react-notion-x/src/components/lite-youtube-embed.tsx @@ -10,18 +10,7 @@ const qs = (params: Record) => { .join('&') } -export const LiteYouTubeEmbed: React.FC<{ - id: string - defaultPlay?: boolean - mute?: boolean - lazyImage?: boolean - iframeTitle?: string - alt?: string - params?: Record - adLinksPreconnect?: boolean - style?: React.CSSProperties - className?: string -}> = ({ +export function LiteYouTubeEmbed({ id, defaultPlay = false, mute = false, @@ -32,7 +21,18 @@ export const LiteYouTubeEmbed: React.FC<{ adLinksPreconnect = true, style, className -}) => { +}: { + id: string + defaultPlay?: boolean + mute?: boolean + lazyImage?: boolean + iframeTitle?: string + alt?: string + params?: Record + adLinksPreconnect?: boolean + style?: React.CSSProperties + className?: string +}) { const muteParam = mute || defaultPlay ? '1' : '0' // Default play must be muted const queryString = React.useMemo( () => qs({ autoplay: '1', mute: muteParam, ...params }), diff --git a/packages/react-notion-x/src/components/mention-preview-card.tsx b/packages/react-notion-x/src/components/mention-preview-card.tsx index 70a9ae08f..b86110fa1 100644 --- a/packages/react-notion-x/src/components/mention-preview-card.tsx +++ b/packages/react-notion-x/src/components/mention-preview-card.tsx @@ -6,13 +6,19 @@ function capitalizeFirstLetter(str?: string) { return str.charAt(0).toUpperCase() + str.slice(1) } -export const MentionPreviewCard: React.FC<{ +export function MentionPreviewCard({ + owner, + lastUpdated, + externalImage, + title, + domain +}: { owner?: string lastUpdated?: string | null title: string domain: string externalImage?: React.ReactNode -}> = ({ owner, lastUpdated, externalImage, title, domain }) => { +}) { return (
{externalImage && ( diff --git a/packages/react-notion-x/src/components/page-aside.tsx b/packages/react-notion-x/src/components/page-aside.tsx index 843183b3a..84a3f62be 100644 --- a/packages/react-notion-x/src/components/page-aside.tsx +++ b/packages/react-notion-x/src/components/page-aside.tsx @@ -4,15 +4,7 @@ import * as React from 'react' import { cs } from '../utils' -export const PageAside: React.FC<{ - toc: Array - activeSection: string | null - setActiveSection: (activeSection: string | null) => unknown - hasToc: boolean - hasAside: boolean - pageAside?: React.ReactNode - className?: string -}> = ({ +export function PageAside({ toc, activeSection, setActiveSection, @@ -20,7 +12,15 @@ export const PageAside: React.FC<{ hasToc, hasAside, className -}) => { +}: { + toc: Array + activeSection: string | null + setActiveSection: (activeSection: string | null) => unknown + hasToc: boolean + hasAside: boolean + pageAside?: React.ReactNode + className?: string +}) { const throttleMs = 100 const actionSectionScrollSpy = React.useMemo( () => diff --git a/packages/react-notion-x/src/components/page-icon.tsx b/packages/react-notion-x/src/components/page-icon.tsx index 319f81b99..a0a1a0d6b 100644 --- a/packages/react-notion-x/src/components/page-icon.tsx +++ b/packages/react-notion-x/src/components/page-icon.tsx @@ -16,19 +16,19 @@ const isIconBlock = (value: Block): value is PageBlock | CalloutBlock => { ) } -export const PageIconImpl: React.FC<{ - block: Block - className?: string - inline?: boolean - hideDefaultIcon?: boolean - defaultIcon?: string -}> = ({ +export function PageIconImpl({ block, className, inline = true, hideDefaultIcon = false, defaultIcon -}) => { +}: { + block: Block + className?: string + inline?: boolean + hideDefaultIcon?: boolean + defaultIcon?: string | null +}) { const { mapImageUrl, recordMap, darkMode } = useNotionContext() let isImage = false let content: any = null diff --git a/packages/react-notion-x/src/components/page-title.tsx b/packages/react-notion-x/src/components/page-title.tsx index f205d4491..2163652d6 100644 --- a/packages/react-notion-x/src/components/page-title.tsx +++ b/packages/react-notion-x/src/components/page-title.tsx @@ -7,11 +7,16 @@ import { cs } from '../utils' import { PageIcon } from './page-icon' import { Text } from './text' -export const PageTitleImpl: React.FC<{ +export function PageTitleImpl({ + block, + className, + defaultIcon, + ...rest +}: { block: Block className?: string - defaultIcon?: string -}> = ({ block, className, defaultIcon, ...rest }) => { + defaultIcon?: string | null +}) { const { recordMap } = useNotionContext() if (!block) return null diff --git a/packages/react-notion-x/src/components/sync-pointer-block.tsx b/packages/react-notion-x/src/components/sync-pointer-block.tsx index cabd7a309..9d525e0bf 100644 --- a/packages/react-notion-x/src/components/sync-pointer-block.tsx +++ b/packages/react-notion-x/src/components/sync-pointer-block.tsx @@ -6,10 +6,13 @@ import { import { NotionBlockRenderer } from '../renderer' -export const SyncPointerBlock: React.FC<{ +export function SyncPointerBlock({ + block, + level +}: { block: BlockType level: number -}> = ({ block, level }) => { +}) { if (!block) { if (process.env.NODE_ENV !== 'production') { console.warn('missing sync pointer block') diff --git a/packages/react-notion-x/src/components/text.tsx b/packages/react-notion-x/src/components/text.tsx index e56b4ddee..b039cea56 100644 --- a/packages/react-notion-x/src/components/text.tsx +++ b/packages/react-notion-x/src/components/text.tsx @@ -20,13 +20,18 @@ import { PageTitle } from './page-title' * TODO: I think this implementation would be more correct if the reduce just added * attributes to the final element's style. */ -export const Text: React.FC<{ +export function Text({ + value, + block, + linkProps, + linkProtocol +}: { value?: Decoration[] block: Block linkProps?: any linkProtocol?: string inline?: boolean // TODO: currently unused -}> = ({ value, block, linkProps, linkProtocol }) => { +}) { const { components, recordMap, mapPageUrl, mapImageUrl, rootDomain } = useNotionContext() diff --git a/packages/react-notion-x/src/context.tsx b/packages/react-notion-x/src/context.tsx index e448517a5..a96404269 100644 --- a/packages/react-notion-x/src/context.tsx +++ b/packages/react-notion-x/src/context.tsx @@ -36,8 +36,8 @@ export interface NotionContext { linkTableTitleProperties: boolean isLinkCollectionToUrlProperty: boolean - defaultPageIcon?: string - defaultPageCover?: string + defaultPageIcon?: string | null + defaultPageCover?: string | null defaultPageCoverPosition?: number zoom: any @@ -67,27 +67,31 @@ export interface PartialNotionContext { showTableOfContents?: boolean minTableOfContentsItems?: number - defaultPageIcon?: string - defaultPageCover?: string + defaultPageIcon?: string | null + defaultPageCover?: string | null defaultPageCoverPosition?: number zoom?: any } -const DefaultLink: React.FC = (props) => ( - -) +function DefaultLink(props: any) { + return +} const DefaultLinkMemo = React.memo(DefaultLink) -const DefaultPageLink: React.FC = (props) => +function DefaultPageLink(props: any) { + return +} const DefaultPageLinkMemo = React.memo(DefaultPageLink) -const DefaultEmbed = (props: any) => +function DefaultEmbed(props: any) { + return +} const DefaultHeader = Header // eslint-disable-next-line @typescript-eslint/no-unused-vars -export const dummyLink = ({ href, rel, target, title, ...rest }: any) => ( - -) +export function dummyLink({ href, rel, target, title, ...rest }: any) { + return +} const dummyComponent = (name: string) => () => { console.warn( @@ -139,6 +143,8 @@ const defaultComponents: NotionComponents = { Embed: DefaultEmbed } +console.log('DefaultHeader', { DefaultHeader, Header, defaultComponents }) + const defaultNotionContext: NotionContext = { recordMap: { block: {}, @@ -168,8 +174,8 @@ const defaultNotionContext: NotionContext = { showTableOfContents: false, minTableOfContentsItems: 3, - defaultPageIcon: undefined, - defaultPageCover: undefined, + defaultPageIcon: null, + defaultPageCover: null, defaultPageCoverPosition: 0.5, zoom: null @@ -177,18 +183,16 @@ const defaultNotionContext: NotionContext = { const ctx = React.createContext(defaultNotionContext) -export const NotionContextProvider: React.FC< - PartialNotionContext & { - children?: React.ReactNode - } -> = ({ +export function NotionContextProvider({ components: themeComponents = {}, children, mapPageUrl, mapImageUrl, rootPageId, ...rest -}) => { +}: PartialNotionContext & { + children?: React.ReactNode +}) { for (const key of Object.keys(rest)) { if ((rest as any)[key] === undefined) { delete (rest as any)[key] @@ -230,6 +234,9 @@ export const NotionContextProvider: React.FC< [mapImageUrl, mapPageUrl, wrappedThemeComponents, rootPageId, rest] ) + console.log('NotionContextProvider', { value }) + console.log({ rest, defaultComponents, wrappedThemeComponents }) + return {children} } diff --git a/packages/react-notion-x/src/icons/chevron-down-icon.tsx b/packages/react-notion-x/src/icons/chevron-down-icon.tsx index 486493c90..7bd50cff9 100644 --- a/packages/react-notion-x/src/icons/chevron-down-icon.tsx +++ b/packages/react-notion-x/src/icons/chevron-down-icon.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -export const ChevronDownIcon = (props: any) => { +export function ChevronDownIcon(props: any) { const { className, ...rest } = props return ( diff --git a/packages/react-notion-x/src/icons/clear-icon.tsx b/packages/react-notion-x/src/icons/clear-icon.tsx index 551f4c44d..daeba717c 100644 --- a/packages/react-notion-x/src/icons/clear-icon.tsx +++ b/packages/react-notion-x/src/icons/clear-icon.tsx @@ -2,7 +2,7 @@ import * as React from 'react' import { cs } from '../utils' -export const ClearIcon = (props: any) => { +export function ClearIcon(props: any) { const { className, ...rest } = props return ( diff --git a/packages/react-notion-x/src/icons/collection-view-icon.tsx b/packages/react-notion-x/src/icons/collection-view-icon.tsx index 6fb547801..56b9f684f 100644 --- a/packages/react-notion-x/src/icons/collection-view-icon.tsx +++ b/packages/react-notion-x/src/icons/collection-view-icon.tsx @@ -1,4 +1,3 @@ -import type * as React from 'react' import { type CollectionViewType } from 'notion-types' import CollectionViewBoardIcon from './collection-view-board' @@ -20,10 +19,7 @@ const iconMap = { calendar: CollectionViewCalendarIcon } -export const CollectionViewIcon: React.FC = ({ - type, - ...rest -}) => { +export function CollectionViewIcon({ type, ...rest }: CollectionViewIconProps) { const icon = iconMap[type] as any if (!icon) { return null diff --git a/packages/react-notion-x/src/icons/default-page-icon.tsx b/packages/react-notion-x/src/icons/default-page-icon.tsx index 5c2ac7ac6..53fd2a411 100644 --- a/packages/react-notion-x/src/icons/default-page-icon.tsx +++ b/packages/react-notion-x/src/icons/default-page-icon.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -export const DefaultPageIcon = (props: any) => { +export function DefaultPageIcon(props: any) { const { className, ...rest } = props return ( diff --git a/packages/react-notion-x/src/icons/empty-icon.tsx b/packages/react-notion-x/src/icons/empty-icon.tsx index 53ad3409c..a09be562b 100644 --- a/packages/react-notion-x/src/icons/empty-icon.tsx +++ b/packages/react-notion-x/src/icons/empty-icon.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -export const EmptyIcon = (props: any) => { +export function EmptyIcon(props: any) { const { className, ...rest } = props return ( diff --git a/packages/react-notion-x/src/icons/file-icon.tsx b/packages/react-notion-x/src/icons/file-icon.tsx index 79abf7076..f772a8fa1 100644 --- a/packages/react-notion-x/src/icons/file-icon.tsx +++ b/packages/react-notion-x/src/icons/file-icon.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -export const FileIcon = (props: any) => { +export function FileIcon(props: any) { const { className, ...rest } = props return ( diff --git a/packages/react-notion-x/src/icons/link-icon.tsx b/packages/react-notion-x/src/icons/link-icon.tsx index 872d7a92c..74a6c6786 100644 --- a/packages/react-notion-x/src/icons/link-icon.tsx +++ b/packages/react-notion-x/src/icons/link-icon.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -export const LinkIcon = (props: any) => { +export function LinkIcon(props: any) { const { className, ...rest } = props return ( { +export function LoadingIcon(props: any) { const { className, ...rest } = props return ( diff --git a/packages/react-notion-x/src/icons/property-icon.tsx b/packages/react-notion-x/src/icons/property-icon.tsx index 5275ffea6..c9fe633b9 100644 --- a/packages/react-notion-x/src/icons/property-icon.tsx +++ b/packages/react-notion-x/src/icons/property-icon.tsx @@ -1,4 +1,3 @@ -import type * as React from 'react' import { type PropertyType } from 'notion-types' import CheckboxIcon from './type-checkbox' @@ -46,10 +45,7 @@ const iconMap = { last_edited_by: Person2Icon } -export const PropertyIcon: React.FC = ({ - type, - ...rest -}) => { +export function PropertyIcon({ type, ...rest }: PropertyIconProps) { const icon = iconMap[type] as any if (!icon) return null diff --git a/packages/react-notion-x/src/icons/search-icon.tsx b/packages/react-notion-x/src/icons/search-icon.tsx index 6120a11b9..377e109d2 100644 --- a/packages/react-notion-x/src/icons/search-icon.tsx +++ b/packages/react-notion-x/src/icons/search-icon.tsx @@ -2,7 +2,7 @@ import * as React from 'react' import { cs } from '../utils' -export const SearchIcon = (props: any) => { +export function SearchIcon(props: any) { const { className, ...rest } = props return ( diff --git a/packages/react-notion-x/src/next.tsx b/packages/react-notion-x/src/next.tsx index 182e77eed..ffdcc2c65 100644 --- a/packages/react-notion-x/src/next.tsx +++ b/packages/react-notion-x/src/next.tsx @@ -37,8 +37,8 @@ export const wrapNextImage = (NextImage: any): React.FC => { }, isEqual) } -export const wrapNextLink = (NextLink: any): React.FC => - function ReactNotionXNextLink({ +export function wrapNextLink(NextLink: any) { + return ({ href, as, passHref, @@ -48,7 +48,7 @@ export const wrapNextLink = (NextLink: any): React.FC => shallow, locale, ...linkProps - }) { + }: any) => { return ( => ) } +} diff --git a/packages/react-notion-x/src/renderer.tsx b/packages/react-notion-x/src/renderer.tsx index 4eb50990f..4c09f0697 100644 --- a/packages/react-notion-x/src/renderer.tsx +++ b/packages/react-notion-x/src/renderer.tsx @@ -11,7 +11,31 @@ import { type SearchNotionFn } from './types' -export const NotionRenderer: React.FC<{ +export function NotionRenderer({ + components, + recordMap, + mapPageUrl, + mapImageUrl, + searchNotion, + isShowingSearch, + onHideSearch, + fullPage, + rootPageId, + rootDomain, + darkMode, + previewImages, + forceCustomImages, + showCollectionViewDropdown, + linkTableTitleProperties, + isLinkCollectionToUrlProperty, + isImageZoomable = true, + showTableOfContents, + minTableOfContentsItems, + defaultPageIcon, + defaultPageCover, + defaultPageCoverPosition, + ...rest +}: { recordMap: ExtendedRecordMap components?: Partial @@ -57,31 +81,7 @@ export const NotionRenderer: React.FC<{ blockId?: string hideBlockId?: boolean disableHeader?: boolean -}> = ({ - components, - recordMap, - mapPageUrl, - mapImageUrl, - searchNotion, - isShowingSearch, - onHideSearch, - fullPage, - rootPageId, - rootDomain, - darkMode, - previewImages, - forceCustomImages, - showCollectionViewDropdown, - linkTableTitleProperties, - isLinkCollectionToUrlProperty, - isImageZoomable = true, - showTableOfContents, - minTableOfContentsItems, - defaultPageIcon, - defaultPageCover, - defaultPageCoverPosition, - ...rest -}) => { +}) { const zoom = React.useMemo( () => typeof window !== 'undefined' && @@ -123,7 +123,11 @@ export const NotionRenderer: React.FC<{ ) } -export const NotionBlockRenderer: React.FC<{ +export function NotionBlockRenderer({ + level = 0, + blockId, + ...props +}: { className?: string bodyClassName?: string header?: React.ReactNode @@ -133,7 +137,7 @@ export const NotionBlockRenderer: React.FC<{ blockId?: string hideBlockId?: boolean level?: number -}> = ({ level = 0, blockId, ...props }) => { +}) { const { recordMap } = useNotionContext() const id = blockId || Object.keys(recordMap.block)[0]! const block = recordMap.block[id]?.value @@ -145,17 +149,18 @@ export const NotionBlockRenderer: React.FC<{ return null } + console.log('NotionBlockRenderer', { id, block }) return ( - {block?.content?.map((contentBlockId) => ( + {/* {block?.content?.map((contentBlockId) => ( - ))} + ))} */} ) } diff --git a/packages/react-notion-x/src/third-party/code.tsx b/packages/react-notion-x/src/third-party/code.tsx index 839c0937c..6cf762778 100644 --- a/packages/react-notion-x/src/third-party/code.tsx +++ b/packages/react-notion-x/src/third-party/code.tsx @@ -19,11 +19,15 @@ import { useNotionContext } from '../context' import CopyIcon from '../icons/copy' import { cs } from '../utils' -export const Code: React.FC<{ +export function Code({ + block, + defaultLanguage = 'typescript', + className +}: { block: CodeBlock defaultLanguage?: string className?: string -}> = ({ block, defaultLanguage = 'typescript', className }) => { +}) { const [isCopied, setIsCopied] = React.useState(false) const copyTimeout = React.useRef() const { recordMap } = useNotionContext() diff --git a/packages/react-notion-x/src/third-party/collection-card.tsx b/packages/react-notion-x/src/third-party/collection-card.tsx index b1be9e5bf..c16e7b77c 100644 --- a/packages/react-notion-x/src/third-party/collection-card.tsx +++ b/packages/react-notion-x/src/third-party/collection-card.tsx @@ -8,7 +8,7 @@ import { type CollectionCardProps } from '../types' import { cs } from '../utils' import { Property } from './property' -export const CollectionCard: React.FC = ({ +export function CollectionCard({ collection, block, cover, @@ -17,7 +17,7 @@ export const CollectionCard: React.FC = ({ properties, className, ...rest -}) => { +}: CollectionCardProps) { const ctx = useNotionContext() const { components, diff --git a/packages/react-notion-x/src/third-party/collection-column-title.tsx b/packages/react-notion-x/src/third-party/collection-column-title.tsx index fa0700624..6a2992ba9 100644 --- a/packages/react-notion-x/src/third-party/collection-column-title.tsx +++ b/packages/react-notion-x/src/third-party/collection-column-title.tsx @@ -3,9 +3,11 @@ import { type CollectionPropertySchema } from 'notion-types' import { PropertyIcon } from '../icons/property-icon' -export const CollectionColumnTitle: React.FC<{ +export function CollectionColumnTitle({ + schema +}: { schema: CollectionPropertySchema -}> = ({ schema }) => { +}) { return (
= ({ +export function CollectionGroup({ collectionViewComponent: CollectionViewComponent, collection, collectionGroup, @@ -13,7 +13,7 @@ export const CollectionGroup: React.FC = ({ summaryProps, detailsProps, ...rest -}) => { +}: CollectionGroupProps) { if (hidden) return null return ( diff --git a/packages/react-notion-x/src/third-party/collection-row.tsx b/packages/react-notion-x/src/third-party/collection-row.tsx index af03adbf2..b4798f984 100644 --- a/packages/react-notion-x/src/third-party/collection-row.tsx +++ b/packages/react-notion-x/src/third-party/collection-row.tsx @@ -6,11 +6,15 @@ import { cs } from '../utils' import { CollectionColumnTitle } from './collection-column-title' import { Property } from './property' -export const CollectionRow: React.FC<{ +export function CollectionRow({ + block, + pageHeader = false, + className +}: { block: PageBlock pageHeader?: boolean className?: string -}> = ({ block, pageHeader = false, className }) => { +}) { const { recordMap } = useNotionContext() const collectionId = block.parent_id const collection = recordMap.collection[collectionId]?.value diff --git a/packages/react-notion-x/src/third-party/collection-view-board.tsx b/packages/react-notion-x/src/third-party/collection-view-board.tsx index 5f4e347c5..e6d2533ca 100644 --- a/packages/react-notion-x/src/third-party/collection-view-board.tsx +++ b/packages/react-notion-x/src/third-party/collection-view-board.tsx @@ -11,12 +11,12 @@ import { CollectionGroup } from './collection-group' import { getCollectionGroups } from './collection-utils' import { Property } from './property' -export const CollectionViewBoard: React.FC = ({ +export function CollectionViewBoard({ collection, collectionView, collectionData, padding -}) => { +}: CollectionViewProps) { const isGroupedCollection = collectionView?.format?.collection_group_by if (isGroupedCollection) { diff --git a/packages/react-notion-x/src/third-party/collection-view-gallery.tsx b/packages/react-notion-x/src/third-party/collection-view-gallery.tsx index d8d6950b8..147de2670 100644 --- a/packages/react-notion-x/src/third-party/collection-view-gallery.tsx +++ b/packages/react-notion-x/src/third-party/collection-view-gallery.tsx @@ -11,11 +11,11 @@ import { getCollectionGroups } from './collection-utils' const defaultBlockIds: string[] = [] -export const CollectionViewGallery: React.FC = ({ +export function CollectionViewGallery({ collection, collectionView, collectionData -}) => { +}: CollectionViewProps) { const isGroupedCollection = collectionView?.format?.collection_group_by if (isGroupedCollection) { diff --git a/packages/react-notion-x/src/third-party/collection-view-list.tsx b/packages/react-notion-x/src/third-party/collection-view-list.tsx index 3e28c1596..4c430bf76 100644 --- a/packages/react-notion-x/src/third-party/collection-view-list.tsx +++ b/packages/react-notion-x/src/third-party/collection-view-list.tsx @@ -10,11 +10,11 @@ import { Property } from './property' const defaultBlockIds: string[] = [] -export const CollectionViewList: React.FC = ({ +export function CollectionViewList({ collection, collectionView, collectionData -}) => { +}: CollectionViewProps) { const isGroupedCollection = collectionView?.format?.collection_group_by if (isGroupedCollection) { diff --git a/packages/react-notion-x/src/third-party/collection-view-table.tsx b/packages/react-notion-x/src/third-party/collection-view-table.tsx index b7d422a1c..5f945aa0d 100644 --- a/packages/react-notion-x/src/third-party/collection-view-table.tsx +++ b/packages/react-notion-x/src/third-party/collection-view-table.tsx @@ -10,13 +10,13 @@ import { Property } from './property' const defaultBlockIds: string[] = [] -export const CollectionViewTable: React.FC = ({ +export function CollectionViewTable({ collection, collectionView, collectionData, padding, width -}) => { +}: CollectionViewProps) { const isGroupedCollection = collectionView?.format?.collection_group_by if (isGroupedCollection) { diff --git a/packages/react-notion-x/src/third-party/collection-view.tsx b/packages/react-notion-x/src/third-party/collection-view.tsx index f5d8281f4..6eb8864d4 100644 --- a/packages/react-notion-x/src/third-party/collection-view.tsx +++ b/packages/react-notion-x/src/third-party/collection-view.tsx @@ -6,7 +6,7 @@ import { CollectionViewGallery } from './collection-view-gallery' import { CollectionViewList } from './collection-view-list' import { CollectionViewTable } from './collection-view-table' -export const CollectionViewImpl: React.FC = (props) => { +export function CollectionViewImpl(props: CollectionViewProps) { const { collectionView } = props switch (collectionView.type) { diff --git a/packages/react-notion-x/src/third-party/collection.tsx b/packages/react-notion-x/src/third-party/collection.tsx index f328e65ce..0d6b8ee80 100644 --- a/packages/react-notion-x/src/third-party/collection.tsx +++ b/packages/react-notion-x/src/third-party/collection.tsx @@ -20,14 +20,18 @@ import { CollectionView } from './collection-view' const isServer = typeof window === 'undefined' -export const Collection: React.FC<{ +export function Collection({ + block, + className, + ctx +}: { block: | types.CollectionViewBlock | types.CollectionViewPageBlock | types.PageBlock className?: string ctx: NotionContext -}> = ({ block, className, ctx }) => { +}) { /** * NOTE: there is a weird side effect of us using multiple bundles for * collections, where `useNotionContext` returns a *different* context than for @@ -73,10 +77,13 @@ export const Collection: React.FC<{ } } -const CollectionViewBlock: React.FC<{ +function CollectionViewBlock({ + block, + className +}: { block: types.CollectionViewBlock | types.CollectionViewPageBlock className?: string -}> = ({ block, className }) => { +}) { const { recordMap, showCollectionViewDropdown } = useNotionContext() const { view_ids: viewIds } = block const collectionId = getBlockCollectionId(block, recordMap)! @@ -220,11 +227,15 @@ const CollectionViewBlock: React.FC<{ ) } -const CollectionViewTabs: React.FC<{ +function CollectionViewTabs({ + collectionViewId, + viewIds, + onChangeView +}: { collectionViewId: string viewIds: string[] onChangeView: (viewId: string) => unknown -}> = ({ collectionViewId, viewIds, onChangeView }) => { +}) { const { recordMap } = useNotionContext() return ( @@ -248,11 +259,16 @@ const CollectionViewTabs: React.FC<{ ) } -const CollectionViewColumnDesc: React.FC<{ +function CollectionViewColumnDesc({ + collectionView, + className, + children, + ...rest +}: { collectionView?: types.CollectionView className?: string children?: React.ReactNode -}> = ({ collectionView, className, children, ...rest }) => { +}) { if (!collectionView) return null const { type } = collectionView diff --git a/packages/react-notion-x/src/third-party/equation.tsx b/packages/react-notion-x/src/third-party/equation.tsx index e9849528e..6a3f402f3 100644 --- a/packages/react-notion-x/src/third-party/equation.tsx +++ b/packages/react-notion-x/src/third-party/equation.tsx @@ -11,12 +11,18 @@ const katexSettings = { strict: false } -export const Equation: React.FC<{ +export function Equation({ + block, + math, + inline = false, + className, + ...rest +}: { block: EquationBlock math?: string inline?: boolean className?: string -}> = ({ block, math, inline = false, className, ...rest }) => { +}) { const { recordMap } = useNotionContext() math = math || getBlockTitle(block, recordMap) if (!math) return null diff --git a/packages/react-notion-x/src/third-party/pdf.tsx b/packages/react-notion-x/src/third-party/pdf.tsx index a44e45b66..90f5b6695 100644 --- a/packages/react-notion-x/src/third-party/pdf.tsx +++ b/packages/react-notion-x/src/third-party/pdf.tsx @@ -4,7 +4,7 @@ import { Document, Page, pdfjs } from 'react-pdf' // ensure pdfjs can find its worker script regardless of how react-notion-x is bundled pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.js` -export const Pdf: React.FC<{ file: string }> = ({ file, ...rest }) => { +export function Pdf({ file, ...rest }: { file: string }) { const [numPages, setNumPages] = React.useState(0) function onDocumentLoadSuccess({ numPages }: { numPages: number }) { diff --git a/packages/react-notion-x/src/third-party/property.tsx b/packages/react-notion-x/src/third-party/property.tsx index ae216e7ad..8476d6941 100644 --- a/packages/react-notion-x/src/third-party/property.tsx +++ b/packages/react-notion-x/src/third-party/property.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react/function-component-definition */ import type * as types from 'notion-types' import format from 'date-fns/format/index.js' import formatNumber from 'format-number' @@ -29,7 +30,7 @@ export interface IPropertyProps { * This corresponds to rendering the content of a single cell in a table. * Property rendering is re-used across all the different types of collection views. */ -export const Property: React.FC = (props) => { +export function Property(props: IPropertyProps) { const { components } = useNotionContext() if (components.Property) { @@ -39,7 +40,7 @@ export const Property: React.FC = (props) => { } } -export const PropertyImpl: React.FC = (props) => { +export function PropertyImpl(props: IPropertyProps) { const { components, mapImageUrl, mapPageUrl } = useNotionContext() const { schema,