feat(base): inline base embed — node registration, slash command, and renderer view

This commit is contained in:
Philipinho
2026-04-27 01:54:59 +01:00
parent 3826e5a50d
commit 7f8ed733a3
3 changed files with 75 additions and 0 deletions
@@ -0,0 +1,48 @@
import { NodeViewWrapper, NodeViewProps } from '@tiptap/react';
import { Box, Text } from '@mantine/core';
import { BaseTable } from '@/features/base/components/base-table';
import { useBaseQuery } from '@/features/base/queries/base-query';
export function BaseEmbedView({ node }: NodeViewProps) {
const pageId = node.attrs.pageId as string | null;
if (!pageId) {
return (
<NodeViewWrapper>
<Box p="md">
<Text c="red">Invalid base embed (missing page id)</Text>
</Box>
</NodeViewWrapper>
);
}
const { isLoading, isError } = useBaseQuery(pageId);
if (isLoading) {
return (
<NodeViewWrapper>
<Box p="md">
<Text c="dimmed">Loading...</Text>
</Box>
</NodeViewWrapper>
);
}
if (isError) {
return (
<NodeViewWrapper>
<Box p="md" bg="gray.0" style={{ borderRadius: 8 }}>
<Text c="dimmed">You don't have access to this database.</Text>
</Box>
</NodeViewWrapper>
);
}
return (
<NodeViewWrapper>
<Box style={{ minHeight: 200 }}>
<BaseTable pageId={pageId} />
</Box>
</NodeViewWrapper>
);
}
@@ -52,6 +52,7 @@ import {
VimeoIcon,
YoutubeIcon,
} from "@/components/icons";
import api from "@/lib/api-client";
const CommandGroups: SlashMenuGroupedItemsType = {
basic: [
@@ -477,6 +478,25 @@ const CommandGroups: SlashMenuGroupedItemsType = {
editor.chain().focus().deleteRange(range).insertSubpages().run();
},
},
{
title: "Database",
description: "Insert an inline database on this page",
searchTerms: ["database", "base", "table", "grid", "spreadsheet"],
icon: IconTable,
command: async ({ editor, range }: CommandProps) => {
// @ts-ignore
const parentPageId = editor.storage?.pageId as string | undefined;
if (!parentPageId) return;
editor.chain().focus().deleteRange(range).run();
const res = await api.post<{ id: string }>("/bases/inline-embed", {
parentPageId,
});
editor.commands.insertBaseEmbed({ pageId: res.data.id });
},
},
{
title: "2 Columns",
description: "Split content into two columns.",