fix(base): show skeleton while inline embed is being created, anchor at slash position

The Database slash command deleted the trigger text and then awaited
the create-base API before inserting the embed. During the wait the
editor sat empty (no visible state), and by the time the embed was
inserted the editor's selection had often drifted — so the new node
landed in the wrong place and the page appeared to "jump up" when the
response arrived.

Insert a placeholder baseEmbed node synchronously at the slash position
with pageId: null and a unique pendingKey. BaseEmbedView renders
BaseTableSkeleton while pendingKey is set — same skeleton BaseTable
shows on its own initial load, so the swap to the real table is a
visual no-op. Once the API responds, look up the placeholder by its
pendingKey and patch in the real pageId via setNodeMarkup. On API
failure, remove the placeholder and surface a toast. The pendingKey
attribute is non-serializing (parseHTML returns null, renderHTML
returns {}) so a placeholder can't survive a page reload as orphan.
This commit is contained in:
Philipinho
2026-04-27 22:02:42 +01:00
parent bfa85b9835
commit c8086b33e4
3 changed files with 99 additions and 8 deletions
@@ -8,7 +8,10 @@ export interface BaseEmbedOptions {
declare module '@tiptap/core' {
interface Commands<ReturnType> {
baseEmbed: {
insertBaseEmbed: (attrs: { pageId: string }) => ReturnType;
insertBaseEmbed: (attrs: {
pageId: string | null;
pendingKey?: string | null;
}) => ReturnType;
};
}
}
@@ -32,6 +35,16 @@ export const BaseEmbed = Node.create<BaseEmbedOptions>({
renderHTML: (attrs) =>
attrs.pageId ? { 'data-page-id': attrs.pageId } : {},
},
// Transient marker set when the slash command inserts the embed
// before the server has assigned a pageId. The view renders a
// skeleton in this state. Cleared once the API responds and the
// real pageId is patched in. Not serialized — embeds saved with
// a pendingKey would orphan if the page were closed mid-request.
pendingKey: {
default: null,
parseHTML: () => null,
renderHTML: () => ({}),
},
};
},