feat: add support for HTML content in HitlEditPanel and PlateEditor components for only Confluence HITL tool

This commit is contained in:
Anish Sarkar 2026-03-22 02:42:51 +05:30
parent 2bc6a0c3bc
commit a9683bb1dc
8 changed files with 131 additions and 18 deletions

View file

@ -13,6 +13,7 @@ interface HitlEditPanelState {
title: string; title: string;
content: string; content: string;
toolName: string; toolName: string;
contentFormat?: "markdown" | "html";
extraFields?: ExtraField[]; extraFields?: ExtraField[];
onSave: onSave:
| ((title: string, content: string, extraFieldValues?: Record<string, string>) => void) | ((title: string, content: string, extraFieldValues?: Record<string, string>) => void)
@ -25,6 +26,7 @@ const initialState: HitlEditPanelState = {
title: "", title: "",
content: "", content: "",
toolName: "", toolName: "",
contentFormat: undefined,
extraFields: undefined, extraFields: undefined,
onSave: null, onSave: null,
onClose: null, onClose: null,
@ -43,6 +45,7 @@ export const openHitlEditPanelAtom = atom(
title: string; title: string;
content: string; content: string;
toolName: string; toolName: string;
contentFormat?: "markdown" | "html";
extraFields?: ExtraField[]; extraFields?: ExtraField[];
onSave: (title: string, content: string, extraFieldValues?: Record<string, string>) => void; onSave: (title: string, content: string, extraFieldValues?: Record<string, string>) => void;
onClose?: () => void; onClose?: () => void;
@ -56,6 +59,7 @@ export const openHitlEditPanelAtom = atom(
title: payload.title, title: payload.title,
content: payload.content, content: payload.content,
toolName: payload.toolName, toolName: payload.toolName,
contentFormat: payload.contentFormat,
extraFields: payload.extraFields, extraFields: payload.extraFields,
onSave: payload.onSave, onSave: payload.onSave,
onClose: payload.onClose ?? null, onClose: payload.onClose ?? null,

View file

@ -1,7 +1,8 @@
"use client"; "use client";
import { MarkdownPlugin, remarkMdx } from "@platejs/markdown"; import { MarkdownPlugin, remarkMdx } from "@platejs/markdown";
import type { AnyPluginConfig } from "platejs"; import { slateToHtml } from "@slate-serializers/html";
import type { AnyPluginConfig, Descendant, Value } from "platejs";
import { createPlatePlugin, Key, Plate, usePlateEditor } from "platejs/react"; import { createPlatePlugin, Key, Plate, usePlateEditor } from "platejs/react";
import { useEffect, useMemo, useRef } from "react"; import { useEffect, useMemo, useRef } from "react";
import remarkGfm from "remark-gfm"; import remarkGfm from "remark-gfm";
@ -14,8 +15,12 @@ import { Editor, EditorContainer } from "@/components/ui/editor";
export interface PlateEditorProps { export interface PlateEditorProps {
/** Markdown string to load as initial content */ /** Markdown string to load as initial content */
markdown?: string; markdown?: string;
/** HTML string to load as initial content. Takes precedence over `markdown`. */
html?: string;
/** Called when the editor content changes, with serialized markdown */ /** Called when the editor content changes, with serialized markdown */
onMarkdownChange?: (markdown: string) => void; onMarkdownChange?: (markdown: string) => void;
/** Called when the editor content changes, with serialized HTML. Use with the `html` prop. */
onHtmlChange?: (html: string) => void;
/** /**
* Force permanent read-only mode (e.g. public/shared view). * Force permanent read-only mode (e.g. public/shared view).
* When true, the editor cannot be toggled to editing mode. * When true, the editor cannot be toggled to editing mode.
@ -57,7 +62,9 @@ export interface PlateEditorProps {
export function PlateEditor({ export function PlateEditor({
markdown, markdown,
html,
onMarkdownChange, onMarkdownChange,
onHtmlChange,
readOnly = false, readOnly = false,
placeholder = "Type...", placeholder = "Type...",
variant = "default", variant = "default",
@ -71,6 +78,7 @@ export function PlateEditor({
extraPlugins = [], extraPlugins = [],
}: PlateEditorProps) { }: PlateEditorProps) {
const lastMarkdownRef = useRef(markdown); const lastMarkdownRef = useRef(markdown);
const lastHtmlRef = useRef(html);
// Keep a stable ref to the latest onSave callback so the plugin shortcut // Keep a stable ref to the latest onSave callback so the plugin shortcut
// always calls the most recent version without re-creating the editor. // always calls the most recent version without re-creating the editor.
@ -118,17 +126,28 @@ export function PlateEditor({
}, },
}), }),
], ],
// Use markdown deserialization for initial value if provided value: html
value: markdown ? (editor) => editor.api.html.deserialize({ element: html }) as Value
? (editor) => : markdown
editor.getApi(MarkdownPlugin).markdown.deserialize(escapeMdxExpressions(markdown)) ? (editor) =>
: undefined, editor.getApi(MarkdownPlugin).markdown.deserialize(escapeMdxExpressions(markdown))
: undefined,
}); });
// Update editor content when html prop changes externally
useEffect(() => {
if (html !== undefined && html !== lastHtmlRef.current) {
lastHtmlRef.current = html;
const newValue = editor.api.html.deserialize({ element: html });
editor.tf.reset();
editor.tf.setValue(newValue);
}
}, [html, editor]);
// Update editor content when markdown prop changes externally // Update editor content when markdown prop changes externally
// (e.g., version switching in report panel) // (e.g., version switching in report panel)
useEffect(() => { useEffect(() => {
if (markdown !== undefined && markdown !== lastMarkdownRef.current) { if (!html && markdown !== undefined && markdown !== lastMarkdownRef.current) {
lastMarkdownRef.current = markdown; lastMarkdownRef.current = markdown;
const newValue = editor const newValue = editor
.getApi(MarkdownPlugin) .getApi(MarkdownPlugin)
@ -136,7 +155,7 @@ export function PlateEditor({
editor.tf.reset(); editor.tf.reset();
editor.tf.setValue(newValue); editor.tf.setValue(newValue);
} }
}, [markdown, editor]); }, [html, markdown, editor]);
// When not forced read-only, the user can toggle between editing/viewing. // When not forced read-only, the user can toggle between editing/viewing.
const canToggleMode = !readOnly; const canToggleMode = !readOnly;
@ -157,7 +176,10 @@ export function PlateEditor({
// (initialized to true via usePlateEditor, toggled via ModeToolbarButton). // (initialized to true via usePlateEditor, toggled via ModeToolbarButton).
{...(readOnly ? { readOnly: true } : {})} {...(readOnly ? { readOnly: true } : {})}
onChange={({ value }) => { onChange={({ value }) => {
if (onMarkdownChange) { if (onHtmlChange && html) {
const serialized = slateToHtml(value as Descendant[]);
onHtmlChange(serialized);
} else if (onMarkdownChange) {
const md = editor.getApi(MarkdownPlugin).markdown.serialize({ value }); const md = editor.getApi(MarkdownPlugin).markdown.serialize({ value });
lastMarkdownRef.current = md; lastMarkdownRef.current = md;
onMarkdownChange(md); onMarkdownChange(md);

View file

@ -194,6 +194,7 @@ function DateTimePickerField({
export function HitlEditPanelContent({ export function HitlEditPanelContent({
title: initialTitle, title: initialTitle,
content: initialContent, content: initialContent,
contentFormat,
extraFields, extraFields,
onSave, onSave,
onClose, onClose,
@ -202,13 +203,14 @@ export function HitlEditPanelContent({
title: string; title: string;
content: string; content: string;
toolName: string; toolName: string;
contentFormat?: "markdown" | "html";
extraFields?: ExtraField[]; extraFields?: ExtraField[];
onSave: (title: string, content: string, extraFieldValues?: Record<string, string>) => void; onSave: (title: string, content: string, extraFieldValues?: Record<string, string>) => void;
onClose?: () => void; onClose?: () => void;
showCloseButton?: boolean; showCloseButton?: boolean;
}) { }) {
const [editedTitle, setEditedTitle] = useState(initialTitle); const [editedTitle, setEditedTitle] = useState(initialTitle);
const markdownRef = useRef(initialContent); const contentRef = useRef(initialContent);
const [isSaving, setIsSaving] = useState(false); const [isSaving, setIsSaving] = useState(false);
const [extraFieldValues, setExtraFieldValues] = useState<Record<string, string>>(() => { const [extraFieldValues, setExtraFieldValues] = useState<Record<string, string>>(() => {
if (!extraFields) return {}; if (!extraFields) return {};
@ -219,8 +221,8 @@ export function HitlEditPanelContent({
return initial; return initial;
}); });
const handleMarkdownChange = useCallback((md: string) => { const handleContentChange = useCallback((content: string) => {
markdownRef.current = md; contentRef.current = content;
}, []); }, []);
const handleExtraFieldChange = useCallback((key: string, value: string) => { const handleExtraFieldChange = useCallback((key: string, value: string) => {
@ -231,7 +233,7 @@ export function HitlEditPanelContent({
if (!editedTitle.trim()) return; if (!editedTitle.trim()) return;
setIsSaving(true); setIsSaving(true);
const extras = extraFields && extraFields.length > 0 ? extraFieldValues : undefined; const extras = extraFields && extraFields.length > 0 ? extraFieldValues : undefined;
onSave(editedTitle, markdownRef.current, extras); onSave(editedTitle, contentRef.current, extras);
onClose?.(); onClose?.();
}, [editedTitle, onSave, onClose, extraFields, extraFieldValues]); }, [editedTitle, onSave, onClose, extraFields, extraFieldValues]);
@ -299,8 +301,9 @@ export function HitlEditPanelContent({
<div className="flex-1 overflow-hidden"> <div className="flex-1 overflow-hidden">
<PlateEditor <PlateEditor
markdown={initialContent} {...(contentFormat === "html"
onMarkdownChange={handleMarkdownChange} ? { html: initialContent, onHtmlChange: handleContentChange }
: { markdown: initialContent, onMarkdownChange: handleContentChange })}
readOnly={false} readOnly={false}
preset="full" preset="full"
placeholder="Start writing..." placeholder="Start writing..."
@ -328,6 +331,7 @@ function DesktopHitlEditPanel() {
title={panelState.title} title={panelState.title}
content={panelState.content} content={panelState.content}
toolName={panelState.toolName} toolName={panelState.toolName}
contentFormat={panelState.contentFormat}
extraFields={panelState.extraFields} extraFields={panelState.extraFields}
onSave={panelState.onSave} onSave={panelState.onSave}
onClose={closePanel} onClose={closePanel}
@ -361,6 +365,7 @@ function MobileHitlEditDrawer() {
title={panelState.title} title={panelState.title}
content={panelState.content} content={panelState.content}
toolName={panelState.toolName} toolName={panelState.toolName}
contentFormat={panelState.contentFormat}
extraFields={panelState.extraFields} extraFields={panelState.extraFields}
onSave={panelState.onSave} onSave={panelState.onSave}
onClose={closePanel} onClose={closePanel}

View file

@ -170,6 +170,7 @@ export function RightPanel({ documentsPanel }: RightPanelProps) {
title={hitlEditState.title} title={hitlEditState.title}
content={hitlEditState.content} content={hitlEditState.content}
toolName={hitlEditState.toolName} toolName={hitlEditState.toolName}
contentFormat={hitlEditState.contentFormat}
extraFields={hitlEditState.extraFields} extraFields={hitlEditState.extraFields}
onSave={hitlEditState.onSave} onSave={hitlEditState.onSave}
onClose={closeHitlEdit} onClose={closeHitlEdit}

View file

@ -237,6 +237,7 @@ function ApprovalCard({
title: pendingEdits?.title ?? args.title ?? "", title: pendingEdits?.title ?? args.title ?? "",
content: pendingEdits?.content ?? args.content ?? "", content: pendingEdits?.content ?? args.content ?? "",
toolName: "Confluence Page", toolName: "Confluence Page",
contentFormat: "html",
onSave: (newTitle, newContent) => { onSave: (newTitle, newContent) => {
setIsPanelOpen(false); setIsPanelOpen(false);
setPendingEdits({ title: newTitle, content: newContent }); setPendingEdits({ title: newTitle, content: newContent });
@ -334,7 +335,7 @@ function ApprovalCard({
}} }}
> >
<PlateEditor <PlateEditor
markdown={pendingEdits?.content ?? args.content ?? ""} html={pendingEdits?.content ?? args.content ?? ""}
readOnly readOnly
preset="readonly" preset="readonly"
editorVariant="none" editorVariant="none"

View file

@ -254,6 +254,7 @@ function ApprovalCard({
title: editedArgs.title, title: editedArgs.title,
content: editedArgs.content, content: editedArgs.content,
toolName: "Confluence Page", toolName: "Confluence Page",
contentFormat: "html",
onSave: (newTitle, newContent) => { onSave: (newTitle, newContent) => {
setIsPanelOpen(false); setIsPanelOpen(false);
setEditedArgs({ setEditedArgs({
@ -305,7 +306,7 @@ function ApprovalCard({
}} }}
> >
<PlateEditor <PlateEditor
markdown={page.body} html={page.body}
readOnly readOnly
preset="readonly" preset="readonly"
editorVariant="none" editorVariant="none"
@ -348,7 +349,7 @@ function ApprovalCard({
}} }}
> >
<PlateEditor <PlateEditor
markdown={String( html={String(
hasPanelEdits hasPanelEdits
? editedArgs.content ? editedArgs.content
: (actionArgs.new_content ?? args.new_content) : (actionArgs.new_content ?? args.new_content)

View file

@ -72,6 +72,7 @@
"@radix-ui/react-toggle-group": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.10",
"@radix-ui/react-toolbar": "^1.1.11", "@radix-ui/react-toolbar": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.7", "@radix-ui/react-tooltip": "^1.2.7",
"@slate-serializers/html": "^2.2.3",
"@streamdown/code": "^1.0.2", "@streamdown/code": "^1.0.2",
"@streamdown/math": "^1.0.2", "@streamdown/math": "^1.0.2",
"@tabler/icons-react": "^3.34.1", "@tabler/icons-react": "^3.34.1",

View file

@ -161,6 +161,9 @@ importers:
'@radix-ui/react-tooltip': '@radix-ui/react-tooltip':
specifier: ^1.2.7 specifier: ^1.2.7
version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@slate-serializers/html':
specifier: ^2.2.3
version: 2.2.3
'@streamdown/code': '@streamdown/code':
specifier: ^1.0.2 specifier: ^1.0.2
version: 1.0.3(react@19.2.4) version: 1.0.3(react@19.2.4)
@ -3490,6 +3493,12 @@ packages:
'@shikijs/vscode-textmate@10.0.2': '@shikijs/vscode-textmate@10.0.2':
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
'@slate-serializers/dom@2.2.3':
resolution: {integrity: sha512-ONcsA8yTSAwwGRg0ZlwIomGUajuzixm6DdN5aU1xcOT2Z1kvhd57SV1TCKznrdIyxWLSfoGx/+RLP5XHXdBtMQ==}
'@slate-serializers/html@2.2.3':
resolution: {integrity: sha512-DgZJOub2VxzQBwhMcSy/cRuLsppiP3v9thm2ayehN2wNBsBdKv5ur1TsEtMiSIlh0DFPsX7WRhF0BksLs2erLA==}
'@standard-schema/spec@1.1.0': '@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
@ -4364,6 +4373,9 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
css-select@5.1.0:
resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
css-select@5.2.2: css-select@5.2.2:
resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==}
@ -5208,6 +5220,9 @@ packages:
html-void-elements@3.0.0: html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
htmlparser2@9.1.0:
resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==}
icu-minify@4.8.3: icu-minify@4.8.3:
resolution: {integrity: sha512-65Av7FLosNk7bPbmQx5z5XG2Y3T2GFppcjiXh4z1idHeVgQxlDpAmkGoYI0eFzAvrOnjpWTL5FmPDhsdfRMPEA==} resolution: {integrity: sha512-65Av7FLosNk7bPbmQx5z5XG2Y3T2GFppcjiXh4z1idHeVgQxlDpAmkGoYI0eFzAvrOnjpWTL5FmPDhsdfRMPEA==}
@ -6616,6 +6631,9 @@ packages:
slate: '>=0.114.0' slate: '>=0.114.0'
slate-dom: '>=0.119.0' slate-dom: '>=0.119.0'
slate@0.102.0:
resolution: {integrity: sha512-RT+tHgqOyZVB1oFV9Pv99ajwh4OUCN9p28QWdnDTIzaN/kZxMsHeQN39UNAgtkZTVVVygFqeg7/R2jiptCvfyA==}
slate@0.120.0: slate@0.120.0:
resolution: {integrity: sha512-CXK/DADGgMZb4z9RTtXylzIDOxvmNJEF9bXV2bAGkLWhQ3rm7GORY9q0H/W41YJvAGZsLbH7nnrhMYr550hWDQ==} resolution: {integrity: sha512-CXK/DADGgMZb4z9RTtXylzIDOxvmNJEF9bXV2bAGkLWhQ3rm7GORY9q0H/W41YJvAGZsLbH7nnrhMYr550hWDQ==}
@ -6770,6 +6788,9 @@ packages:
tiny-invariant@1.3.1: tiny-invariant@1.3.1:
resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==}
tiny-warning@1.0.3:
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
tinyexec@1.0.2: tinyexec@1.0.2:
resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -6808,6 +6829,9 @@ packages:
tsconfig-paths@3.15.0: tsconfig-paths@3.15.0:
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
tslib@2.6.3:
resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
tslib@2.8.1: tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@ -10206,6 +10230,30 @@ snapshots:
'@shikijs/vscode-textmate@10.0.2': {} '@shikijs/vscode-textmate@10.0.2': {}
'@slate-serializers/dom@2.2.3':
dependencies:
css-select: 5.1.0
dom-serializer: 2.0.0
domhandler: 5.0.3
domutils: 3.2.2
html-entities: 2.6.0
htmlparser2: 9.1.0
slate: 0.102.0
tslib: 2.6.3
'@slate-serializers/html@2.2.3':
dependencies:
'@slate-serializers/dom': 2.2.3
css-select: 5.2.2
dom-serializer: 2.0.0
domhandler: 5.0.3
domutils: 3.2.2
html-entities: 2.6.0
htmlparser2: 9.1.0
slate: 0.102.0
slate-hyperscript: 0.100.0(slate@0.102.0)
tslib: 2.6.3
'@standard-schema/spec@1.1.0': {} '@standard-schema/spec@1.1.0': {}
'@standard-schema/utils@0.3.0': {} '@standard-schema/utils@0.3.0': {}
@ -11071,6 +11119,14 @@ snapshots:
shebang-command: 2.0.0 shebang-command: 2.0.0
which: 2.0.2 which: 2.0.2
css-select@5.1.0:
dependencies:
boolbase: 1.0.0
css-what: 6.2.2
domhandler: 5.0.3
domutils: 3.2.2
nth-check: 2.1.1
css-select@5.2.2: css-select@5.2.2:
dependencies: dependencies:
boolbase: 1.0.0 boolbase: 1.0.0
@ -12158,6 +12214,13 @@ snapshots:
html-void-elements@3.0.0: {} html-void-elements@3.0.0: {}
htmlparser2@9.1.0:
dependencies:
domelementtype: 2.3.0
domhandler: 5.0.3
domutils: 3.2.2
entities: 4.5.0
icu-minify@4.8.3: icu-minify@4.8.3:
dependencies: dependencies:
'@formatjs/icu-messageformat-parser': 3.5.1 '@formatjs/icu-messageformat-parser': 3.5.1
@ -14026,6 +14089,11 @@ snapshots:
slate: 0.120.0 slate: 0.120.0
tiny-invariant: 1.3.1 tiny-invariant: 1.3.1
slate-hyperscript@0.100.0(slate@0.102.0):
dependencies:
is-plain-object: 5.0.0
slate: 0.102.0
slate-hyperscript@0.100.0(slate@0.120.0): slate-hyperscript@0.100.0(slate@0.120.0):
dependencies: dependencies:
is-plain-object: 5.0.0 is-plain-object: 5.0.0
@ -14044,6 +14112,12 @@ snapshots:
slate-dom: 0.119.0(slate@0.120.0) slate-dom: 0.119.0(slate@0.120.0)
tiny-invariant: 1.3.1 tiny-invariant: 1.3.1
slate@0.102.0:
dependencies:
immer: 10.2.0
is-plain-object: 5.0.0
tiny-warning: 1.0.3
slate@0.120.0: {} slate@0.120.0: {}
snake-case@3.0.4: snake-case@3.0.4:
@ -14220,6 +14294,8 @@ snapshots:
tiny-invariant@1.3.1: {} tiny-invariant@1.3.1: {}
tiny-warning@1.0.3: {}
tinyexec@1.0.2: {} tinyexec@1.0.2: {}
tinyglobby@0.2.15: tinyglobby@0.2.15:
@ -14252,6 +14328,8 @@ snapshots:
minimist: 1.2.8 minimist: 1.2.8
strip-bom: 3.0.0 strip-bom: 3.0.0
tslib@2.6.3: {}
tslib@2.8.1: {} tslib@2.8.1: {}
tsx@4.21.0: tsx@4.21.0: