@mp-lb/mdkit 0.0.1-main.4.1 → 0.1.0-main.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/document/MdKitConflictPanel.js +4 -4
  2. package/dist/document/MdKitDocumentToolbar.js +3 -3
  3. package/dist/markdown/MarkdownBubbleMenu.d.ts +1 -1
  4. package/dist/markdown/MarkdownBubbleMenu.js +58 -8
  5. package/dist/markdown/MdKitEditor.js +1 -1
  6. package/dist/markdown/TiptapMarkdownSurface.js +5 -5
  7. package/dist/theme/MdKitThemeEditor.js +1 -1
  8. package/dist/theme/editorTheme.d.ts +1 -1
  9. package/dist/theme/editorTheme.js +15 -15
  10. package/dist/versioning/VersionHistoryPanel.js +2 -2
  11. package/docs/api.md +1 -1
  12. package/docs/shadcn.md +1 -1
  13. package/docs/styling.md +190 -71
  14. package/package.json +6 -2
  15. package/src/styles.css +271 -258
  16. package/dist/core/documentEngine.test.d.ts +0 -1
  17. package/dist/core/documentEngine.test.js +0 -119
  18. package/dist/document/useMdKitDocument.test.d.ts +0 -1
  19. package/dist/document/useMdKitDocument.test.js +0 -151
  20. package/dist/markdown/MdKitEditor.test.d.ts +0 -1
  21. package/dist/markdown/MdKitEditor.test.js +0 -126
  22. package/dist/markdown/normalizeMarkdownSerialization.test.d.ts +0 -1
  23. package/dist/markdown/normalizeMarkdownSerialization.test.js +0 -16
  24. package/dist/markdown/prepareMarkdownForEditorHydration.test.d.ts +0 -1
  25. package/dist/markdown/prepareMarkdownForEditorHydration.test.js +0 -13
  26. package/dist/markdown/preserveMarkdownWhitespace.test.d.ts +0 -1
  27. package/dist/markdown/preserveMarkdownWhitespace.test.js +0 -25
  28. package/dist/test/setup.d.ts +0 -1
  29. package/dist/test/setup.js +0 -13
  30. package/dist/versioning/useMdKitDocumentVersions.test.d.ts +0 -1
  31. package/dist/versioning/useMdKitDocumentVersions.test.js +0 -41
  32. package/docs/.vitepress/dist/404.html +0 -22
  33. package/docs/.vitepress/dist/api.html +0 -120
  34. package/docs/.vitepress/dist/architecture.html +0 -25
  35. package/docs/.vitepress/dist/assets/api.md.asncK3PQ.js +0 -96
  36. package/docs/.vitepress/dist/assets/api.md.asncK3PQ.lean.js +0 -1
  37. package/docs/.vitepress/dist/assets/app.BQvrHyG0.js +0 -1
  38. package/docs/.vitepress/dist/assets/architecture.md.BHQLarmZ.js +0 -1
  39. package/docs/.vitepress/dist/assets/architecture.md.BHQLarmZ.lean.js +0 -1
  40. package/docs/.vitepress/dist/assets/chunks/framework.RRduUuAx.js +0 -19
  41. package/docs/.vitepress/dist/assets/chunks/theme.CkCo6Nk1.js +0 -1
  42. package/docs/.vitepress/dist/assets/index.md.CITl-897.js +0 -137
  43. package/docs/.vitepress/dist/assets/index.md.CITl-897.lean.js +0 -1
  44. package/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  45. package/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  46. package/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  47. package/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  48. package/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  49. package/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  50. package/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  51. package/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  52. package/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  53. package/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  54. package/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  55. package/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  56. package/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  57. package/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  58. package/docs/.vitepress/dist/assets/shadcn.md.C3idOo2N.js +0 -57
  59. package/docs/.vitepress/dist/assets/shadcn.md.C3idOo2N.lean.js +0 -1
  60. package/docs/.vitepress/dist/assets/style.BtrGaL3i.css +0 -1
  61. package/docs/.vitepress/dist/assets/styling.md.B2C6kVFa.js +0 -91
  62. package/docs/.vitepress/dist/assets/styling.md.B2C6kVFa.lean.js +0 -1
  63. package/docs/.vitepress/dist/hashmap.json +0 -1
  64. package/docs/.vitepress/dist/index.html +0 -161
  65. package/docs/.vitepress/dist/shadcn.html +0 -81
  66. package/docs/.vitepress/dist/styling.html +0 -115
  67. package/docs/.vitepress/dist/vp-icons.css +0 -1
@@ -33,9 +33,9 @@ export const MdKitConflictPanel = ({ className, document, title = "Document conf
33
33
  ];
34
34
  const activePreviewOption = previewOptions.find((option) => option.id === activePreview) ??
35
35
  previewOptions[0];
36
- return (_jsxs("section", { className: joinClassNames("mdkit-conflict-panel", className), children: [_jsxs("div", { className: "mdkit-conflict-panel-content", children: [_jsx("h2", { children: title }), _jsx("p", { children: "Remote changes conflict with local edits. Choose the remote document, or keep your local document by overwriting the remote copy." }), document.error ? (_jsx("p", { className: "mdkit-conflict-panel-error", children: document.error })) : null, conflictDetails ? (_jsxs("p", { className: "mdkit-conflict-panel-meta", children: ["Remote version ", String(conflictDetails.remoteVersion ?? "none"), conflictDetails.remoteUpdatedAt
36
+ return (_jsxs("section", { className: joinClassNames("mp-lb-mdkit-conflict-panel", className), children: [_jsxs("div", { className: "mp-lb-mdkit-conflict-panel-content", children: [_jsx("h2", { children: title }), _jsx("p", { children: "Remote changes conflict with local edits. Choose the remote document, or keep your local document by overwriting the remote copy." }), document.error ? (_jsx("p", { className: "mp-lb-mdkit-conflict-panel-error", children: document.error })) : null, conflictDetails ? (_jsxs("p", { className: "mp-lb-mdkit-conflict-panel-meta", children: ["Remote version ", String(conflictDetails.remoteVersion ?? "none"), conflictDetails.remoteUpdatedAt
37
37
  ? ` saved ${new Date(conflictDetails.remoteUpdatedAt).toLocaleTimeString()}`
38
- : ""] })) : null] }), _jsxs("div", { className: "mdkit-conflict-panel-preview", children: [_jsx("div", { className: "mdkit-conflict-panel-tabs", role: "tablist", children: previewOptions.map((option) => (_jsx("button", { type: "button", "aria-selected": activePreviewOption.id === option.id, className: activePreviewOption.id === option.id
39
- ? "mdkit-conflict-panel-tab mdkit-conflict-panel-tab-active"
40
- : "mdkit-conflict-panel-tab", role: "tab", onClick: () => setActivePreview(option.id), children: option.label }, option.id))) }), _jsx("textarea", { "aria-label": `${activePreviewOption.label} conflict content`, readOnly: true, value: activePreviewOption.value })] }), _jsxs("div", { className: "mdkit-conflict-panel-action-row", children: [_jsx("button", { type: "button", className: "mdkit-panel-secondary-action", disabled: isBusy, onClick: () => void runAction("reload", document.resync), children: pendingAction === "reload" ? "Keeping remote..." : "Keep remote" }), _jsx("button", { type: "button", className: "mdkit-panel-secondary-action", disabled: isBusy, onClick: () => void runAction("overwrite", document.forceSave), children: pendingAction === "overwrite" ? "Keeping local..." : "Keep local" })] })] }));
38
+ : ""] })) : null] }), _jsxs("div", { className: "mp-lb-mdkit-conflict-panel-preview", children: [_jsx("div", { className: "mp-lb-mdkit-conflict-panel-tabs", role: "tablist", children: previewOptions.map((option) => (_jsx("button", { type: "button", "aria-selected": activePreviewOption.id === option.id, className: activePreviewOption.id === option.id
39
+ ? "mp-lb-mdkit-conflict-panel-tab mp-lb-mdkit-conflict-panel-tab-active"
40
+ : "mp-lb-mdkit-conflict-panel-tab", role: "tab", onClick: () => setActivePreview(option.id), children: option.label }, option.id))) }), _jsx("textarea", { "aria-label": `${activePreviewOption.label} conflict content`, readOnly: true, value: activePreviewOption.value })] }), _jsxs("div", { className: "mp-lb-mdkit-conflict-panel-action-row", children: [_jsx("button", { type: "button", className: "mp-lb-mdkit-panel-secondary-action", disabled: isBusy, onClick: () => void runAction("reload", document.resync), children: pendingAction === "reload" ? "Keeping remote..." : "Keep remote" }), _jsx("button", { type: "button", className: "mp-lb-mdkit-panel-secondary-action", disabled: isBusy, onClick: () => void runAction("overwrite", document.forceSave), children: pendingAction === "overwrite" ? "Keeping local..." : "Keep local" })] })] }));
41
41
  };
@@ -33,7 +33,7 @@ export const MdKitDocumentToolbar = ({ className, collaboration, document, onOpe
33
33
  : document.saveStatus === "saved"
34
34
  ? "Saved"
35
35
  : "Idle";
36
- return (_jsxs("div", { className: joinClassNames("mdkit-document-toolbar", className), "data-conflict": document.conflict ? "true" : undefined, "data-dirty": document.isDirty ? "true" : undefined, "data-save-status": document.saveStatus, "data-status": status.toLowerCase().replace(/\s+/g, "-"), children: [_jsxs("div", { className: "mdkit-document-toolbar-status", children: [_jsx("strong", { children: status }), _jsx("span", { children: formatUpdatedAt(document.updatedAt) }), _jsxs("span", { children: ["Collaboration ", collaboration ? collaboration.status : "off"] })] }), document.error && !document.conflict ? (_jsx("div", { className: "mdkit-document-toolbar-error", children: document.error })) : null, _jsxs("div", { className: "mdkit-document-toolbar-actions", children: [_jsx("button", { type: "button", disabled: isBusy ||
36
+ return (_jsxs("div", { className: joinClassNames("mp-lb-mdkit-document-toolbar", className), "data-conflict": document.conflict ? "true" : undefined, "data-dirty": document.isDirty ? "true" : undefined, "data-save-status": document.saveStatus, "data-status": status.toLowerCase().replace(/\s+/g, "-"), children: [_jsxs("div", { className: "mp-lb-mdkit-document-toolbar-status", children: [_jsx("strong", { children: status }), _jsx("span", { children: formatUpdatedAt(document.updatedAt) }), _jsxs("span", { children: ["Collaboration ", collaboration ? collaboration.status : "off"] })] }), document.error && !document.conflict ? (_jsx("div", { className: "mp-lb-mdkit-document-toolbar-error", children: document.error })) : null, _jsxs("div", { className: "mp-lb-mdkit-document-toolbar-actions", children: [_jsx("button", { type: "button", disabled: isBusy ||
37
37
  document.conflict ||
38
38
  !hasVersionHistory ||
39
39
  versions?.isLoading ||
@@ -42,7 +42,7 @@ export const MdKitDocumentToolbar = ({ className, collaboration, document, onOpe
42
42
  await onOpenVersionHistory?.();
43
43
  }), children: versions?.isLoading
44
44
  ? "Loading versions..."
45
- : `Version ${String(document.version ?? "none")}` }), document.conflict && onOpenConflict ? (_jsx("button", { type: "button", className: "mdkit-document-toolbar-conflict-trigger", disabled: isBusy, onClick: () => void runAction("conflict", async () => {
45
+ : `Version ${String(document.version ?? "none")}` }), document.conflict && onOpenConflict ? (_jsx("button", { type: "button", className: "mp-lb-mdkit-document-toolbar-conflict-trigger", disabled: isBusy, onClick: () => void runAction("conflict", async () => {
46
46
  await onOpenConflict();
47
- }), children: "Resolve conflict" })) : null] }), document.conflict && showConflictActions ? (_jsxs("div", { className: "mdkit-document-toolbar-conflict", children: [_jsx("span", { children: "Remote changes conflict with local edits." }), _jsx("button", { type: "button", disabled: isBusy, onClick: () => void runAction("reload", document.resync), children: "Keep remote" }), _jsx("button", { type: "button", disabled: isBusy, onClick: () => void runAction("overwrite", document.forceSave), children: "Keep local" })] })) : null] }));
47
+ }), children: "Resolve conflict" })) : null] }), document.conflict && showConflictActions ? (_jsxs("div", { className: "mp-lb-mdkit-document-toolbar-conflict", children: [_jsx("span", { children: "Remote changes conflict with local edits." }), _jsx("button", { type: "button", disabled: isBusy, onClick: () => void runAction("reload", document.resync), children: "Keep remote" }), _jsx("button", { type: "button", disabled: isBusy, onClick: () => void runAction("overwrite", document.forceSave), children: "Keep local" })] })) : null] }));
48
48
  };
@@ -1,4 +1,4 @@
1
- import type { Editor } from "@tiptap/react";
1
+ import { type Editor } from "@tiptap/react";
2
2
  type MarkdownBubbleMenuProps = {
3
3
  editor: Editor;
4
4
  };
@@ -1,7 +1,39 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEditorState } from "@tiptap/react";
2
3
  import { BubbleMenu } from "@tiptap/react/menus";
3
4
  import { Bold, Code2, Heading1, Heading2, Italic, Link2, List, ListOrdered, Quote, Strikethrough, } from "lucide-react";
4
5
  import { joinClassNames } from "../ui/joinClassNames";
6
+ const toolbarActiveStateIsEqual = (left, right) => {
7
+ if (!right) {
8
+ return false;
9
+ }
10
+ return (left.blockquote === right.blockquote &&
11
+ left.bold === right.bold &&
12
+ left.bulletList === right.bulletList &&
13
+ left.codeBlock === right.codeBlock &&
14
+ left.heading1 === right.heading1 &&
15
+ left.heading2 === right.heading2 &&
16
+ left.italic === right.italic &&
17
+ left.link === right.link &&
18
+ left.orderedList === right.orderedList &&
19
+ left.strike === right.strike);
20
+ };
21
+ const useToolbarActiveState = (editor) => useEditorState({
22
+ editor,
23
+ selector: ({ editor: currentEditor }) => ({
24
+ blockquote: currentEditor.isActive("blockquote"),
25
+ bold: currentEditor.isActive("bold"),
26
+ bulletList: currentEditor.isActive("bulletList"),
27
+ codeBlock: currentEditor.isActive("codeBlock"),
28
+ heading1: currentEditor.isActive("heading", { level: 1 }),
29
+ heading2: currentEditor.isActive("heading", { level: 2 }),
30
+ italic: currentEditor.isActive("italic"),
31
+ link: currentEditor.isActive("link"),
32
+ orderedList: currentEditor.isActive("orderedList"),
33
+ strike: currentEditor.isActive("strike"),
34
+ }),
35
+ equalityFn: toolbarActiveStateIsEqual,
36
+ });
5
37
  const setLink = (editor) => {
6
38
  const previousUrl = editor.getAttributes("link").href;
7
39
  const nextUrl = window.prompt("URL", previousUrl);
@@ -19,11 +51,29 @@ const setLink = (editor) => {
19
51
  .setLink({ href: nextUrl })
20
52
  .run();
21
53
  };
22
- const ToolbarButton = ({ ariaLabel, children, isActive, onClick, }) => (_jsx("button", { type: "button", className: joinClassNames("hsk-toolbar-button", isActive && "hsk-toolbar-button-active"), "aria-label": ariaLabel, onClick: onClick, onMouseDown: (event) => event.preventDefault(), children: children }));
23
- export const MarkdownBubbleMenu = ({ editor }) => (_jsxs(BubbleMenu, { appendTo: () => document.body, className: "hsk-toolbar", editor: editor, options: {
24
- placement: "top",
25
- strategy: "fixed",
26
- }, shouldShow: ({ editor: currentEditor, state }) => {
27
- const { empty } = state.selection;
28
- return currentEditor.isEditable && !empty;
29
- }, children: [_jsx(ToolbarButton, { ariaLabel: "Bold", isActive: editor.isActive("bold"), onClick: () => editor.chain().focus().toggleBold().run(), children: _jsx(Bold, {}) }), _jsx(ToolbarButton, { ariaLabel: "Italic", isActive: editor.isActive("italic"), onClick: () => editor.chain().focus().toggleItalic().run(), children: _jsx(Italic, {}) }), _jsx(ToolbarButton, { ariaLabel: "Strikethrough", isActive: editor.isActive("strike"), onClick: () => editor.chain().focus().toggleStrike().run(), children: _jsx(Strikethrough, {}) }), _jsx(ToolbarButton, { ariaLabel: "Code block", isActive: editor.isActive("codeBlock"), onClick: () => editor.chain().focus().toggleCodeBlock().run(), children: _jsx(Code2, {}) }), _jsx("div", { className: "hsk-toolbar-divider" }), _jsx(ToolbarButton, { ariaLabel: "Heading 1", isActive: editor.isActive("heading", { level: 1 }), onClick: () => editor.chain().focus().toggleHeading({ level: 1 }).run(), children: _jsx(Heading1, {}) }), _jsx(ToolbarButton, { ariaLabel: "Heading 2", isActive: editor.isActive("heading", { level: 2 }), onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run(), children: _jsx(Heading2, {}) }), _jsx("div", { className: "hsk-toolbar-divider" }), _jsx(ToolbarButton, { ariaLabel: "Bullet list", isActive: editor.isActive("bulletList"), onClick: () => editor.chain().focus().toggleBulletList().run(), children: _jsx(List, {}) }), _jsx(ToolbarButton, { ariaLabel: "Ordered list", isActive: editor.isActive("orderedList"), onClick: () => editor.chain().focus().toggleOrderedList().run(), children: _jsx(ListOrdered, {}) }), _jsx(ToolbarButton, { ariaLabel: "Blockquote", isActive: editor.isActive("blockquote"), onClick: () => editor.chain().focus().toggleBlockquote().run(), children: _jsx(Quote, {}) }), _jsx("div", { className: "hsk-toolbar-divider" }), _jsx(ToolbarButton, { ariaLabel: "Link", isActive: editor.isActive("link"), onClick: () => setLink(editor), children: _jsx(Link2, {}) })] }));
54
+ const ToolbarButton = ({ ariaLabel, children, isActive, onAction, }) => {
55
+ const runPointerAction = (event) => {
56
+ if (event.pointerType === "mouse" && event.button !== 0) {
57
+ return;
58
+ }
59
+ event.preventDefault();
60
+ event.stopPropagation();
61
+ onAction();
62
+ };
63
+ const runKeyboardAction = (event) => {
64
+ if (event.detail !== 0) {
65
+ return;
66
+ }
67
+ onAction();
68
+ };
69
+ return (_jsx("button", { type: "button", className: joinClassNames("mp-lb-mdkit-toolbar-button", isActive && "mp-lb-mdkit-toolbar-button-active"), "aria-label": ariaLabel, "aria-pressed": isActive, onClick: runKeyboardAction, onPointerDown: runPointerAction, children: children }));
70
+ };
71
+ export const MarkdownBubbleMenu = ({ editor }) => {
72
+ const activeState = useToolbarActiveState(editor);
73
+ return (_jsxs(BubbleMenu, { className: "mp-lb-mdkit-toolbar", editor: editor, options: {
74
+ placement: "top",
75
+ }, shouldShow: ({ editor: currentEditor, state }) => {
76
+ const { empty } = state.selection;
77
+ return currentEditor.isEditable && !empty;
78
+ }, children: [_jsx(ToolbarButton, { ariaLabel: "Bold", isActive: activeState.bold, onAction: () => editor.chain().focus().toggleBold().run(), children: _jsx(Bold, {}) }), _jsx(ToolbarButton, { ariaLabel: "Italic", isActive: activeState.italic, onAction: () => editor.chain().focus().toggleItalic().run(), children: _jsx(Italic, {}) }), _jsx(ToolbarButton, { ariaLabel: "Strikethrough", isActive: activeState.strike, onAction: () => editor.chain().focus().toggleStrike().run(), children: _jsx(Strikethrough, {}) }), _jsx(ToolbarButton, { ariaLabel: "Code block", isActive: activeState.codeBlock, onAction: () => editor.chain().focus().toggleCodeBlock().run(), children: _jsx(Code2, {}) }), _jsx("div", { className: "mp-lb-mdkit-toolbar-divider" }), _jsx(ToolbarButton, { ariaLabel: "Heading 1", isActive: activeState.heading1, onAction: () => editor.chain().focus().toggleHeading({ level: 1 }).run(), children: _jsx(Heading1, {}) }), _jsx(ToolbarButton, { ariaLabel: "Heading 2", isActive: activeState.heading2, onAction: () => editor.chain().focus().toggleHeading({ level: 2 }).run(), children: _jsx(Heading2, {}) }), _jsx("div", { className: "mp-lb-mdkit-toolbar-divider" }), _jsx(ToolbarButton, { ariaLabel: "Bullet list", isActive: activeState.bulletList, onAction: () => editor.chain().focus().toggleBulletList().run(), children: _jsx(List, {}) }), _jsx(ToolbarButton, { ariaLabel: "Ordered list", isActive: activeState.orderedList, onAction: () => editor.chain().focus().toggleOrderedList().run(), children: _jsx(ListOrdered, {}) }), _jsx(ToolbarButton, { ariaLabel: "Blockquote", isActive: activeState.blockquote, onAction: () => editor.chain().focus().toggleBlockquote().run(), children: _jsx(Quote, {}) }), _jsx("div", { className: "mp-lb-mdkit-toolbar-divider" }), _jsx(ToolbarButton, { ariaLabel: "Link", isActive: activeState.link, onAction: () => setLink(editor), children: _jsx(Link2, {}) })] }));
79
+ };
@@ -3,5 +3,5 @@ import { joinClassNames } from "../ui/joinClassNames";
3
3
  import { TiptapMarkdownSurface } from "./TiptapMarkdownSurface";
4
4
  export const MdKitEditor = (props) => {
5
5
  const { className, fillHeight = false, readOnly = false, style, ...surfaceProps } = props;
6
- return (_jsx("div", { className: joinClassNames("mdkit-markdown-editor", fillHeight && "mdkit-markdown-editor-fill-height", className), "data-read-only": readOnly ? "true" : undefined, style: style, children: _jsx(TiptapMarkdownSurface, { readOnly: readOnly, ...surfaceProps }, props.instanceKey) }));
6
+ return (_jsx("div", { className: joinClassNames("mp-lb-mdkit-markdown-editor", fillHeight && "mp-lb-mdkit-markdown-editor-fill-height", className), "data-read-only": readOnly ? "true" : undefined, style: style, children: _jsx(TiptapMarkdownSurface, { readOnly: readOnly, ...surfaceProps }, props.instanceKey) }));
7
7
  };
@@ -91,10 +91,10 @@ export const TiptapMarkdownSurface = (props) => {
91
91
  provider: collaborationProvider,
92
92
  render: (user) => {
93
93
  const cursor = document.createElement("span");
94
- cursor.classList.add("hsk-collaboration-caret");
94
+ cursor.classList.add("mp-lb-mdkit-collaboration-caret");
95
95
  cursor.style.borderColor = user.color;
96
96
  const label = document.createElement("div");
97
- label.classList.add("hsk-collaboration-caret-label");
97
+ label.classList.add("mp-lb-mdkit-collaboration-caret-label");
98
98
  label.style.backgroundColor = user.color;
99
99
  label.textContent = user.name;
100
100
  cursor.appendChild(label);
@@ -118,7 +118,7 @@ export const TiptapMarkdownSurface = (props) => {
118
118
  editable: !readOnly,
119
119
  editorProps: {
120
120
  attributes: {
121
- class: "hsk-tiptap",
121
+ class: "mp-lb-mdkit-tiptap",
122
122
  spellcheck: "false",
123
123
  },
124
124
  },
@@ -215,7 +215,7 @@ export const TiptapMarkdownSurface = (props) => {
215
215
  });
216
216
  }, [editor, markdownValue]);
217
217
  if (!editor) {
218
- return (_jsx("div", { className: "hsk-editor-shell", children: _jsx("div", { className: "hsk-editor-empty", children: collaboration
218
+ return (_jsx("div", { className: "mp-lb-mdkit-editor-shell", children: _jsx("div", { className: "mp-lb-mdkit-editor-empty", children: collaboration
219
219
  ? "Connecting collaboration session..."
220
220
  : "Loading editor..." }) }));
221
221
  }
@@ -426,5 +426,5 @@ export const TiptapMarkdownSurface = (props) => {
426
426
  });
427
427
  queueEditorFocusAtPosition(getEditorPositionAtClientPoint(event.clientX, event.clientY, event.target));
428
428
  };
429
- return (_jsx("div", { className: "hsk-editor-shell", children: _jsxs("div", { ref: editorSurfaceRef, className: "hsk-editor-surface", onPointerDownCapture: focusEditorBackgroundOnPointerDown, onPointerUpCapture: focusEditorBackgroundOnPointerUp, children: [_jsx(MarkdownBubbleMenu, { editor: editor }), _jsx(EditorContent, { editor: editor })] }) }));
429
+ return (_jsx("div", { className: "mp-lb-mdkit-editor-shell", children: _jsxs("div", { ref: editorSurfaceRef, className: "mp-lb-mdkit-editor-surface", onPointerDownCapture: focusEditorBackgroundOnPointerDown, onPointerUpCapture: focusEditorBackgroundOnPointerUp, children: [_jsx(MarkdownBubbleMenu, { editor: editor }), _jsx(EditorContent, { editor: editor })] }) }));
430
430
  };
@@ -6,7 +6,7 @@ export const MdKitThemeEditor = ({ className, onChange, onReset, theme, }) => {
6
6
  ...patch,
7
7
  });
8
8
  };
9
- return (_jsxs("div", { className: ["hsk-theme-editor", className].filter(Boolean).join(" "), children: [_jsxs("label", { children: [_jsx("span", { children: "Background" }), _jsx("input", { type: "color", value: theme.background, onChange: (event) => updateTheme({ background: event.target.value }) })] }), _jsxs("label", { children: [_jsx("span", { children: "Text" }), _jsx("input", { type: "color", value: theme.foreground, onChange: (event) => updateTheme({ foreground: event.target.value }) })] }), _jsxs("label", { children: [_jsx("span", { children: "Link" }), _jsx("input", { type: "color", value: theme.link, onChange: (event) => updateTheme({ link: event.target.value }) })] }), _jsxs("label", { children: [_jsx("span", { children: "Code" }), _jsx("input", { type: "color", value: theme.codeBackground, onChange: (event) => updateTheme({
9
+ return (_jsxs("div", { className: ["mp-lb-mdkit-theme-editor", className].filter(Boolean).join(" "), children: [_jsxs("label", { children: [_jsx("span", { children: "Background" }), _jsx("input", { type: "color", value: theme.background, onChange: (event) => updateTheme({ background: event.target.value }) })] }), _jsxs("label", { children: [_jsx("span", { children: "Text" }), _jsx("input", { type: "color", value: theme.foreground, onChange: (event) => updateTheme({ foreground: event.target.value }) })] }), _jsxs("label", { children: [_jsx("span", { children: "Link" }), _jsx("input", { type: "color", value: theme.link, onChange: (event) => updateTheme({ link: event.target.value }) })] }), _jsxs("label", { children: [_jsx("span", { children: "Code" }), _jsx("input", { type: "color", value: theme.codeBackground, onChange: (event) => updateTheme({
10
10
  codeBackground: event.target.value,
11
11
  muted: event.target.value,
12
12
  }) })] }), _jsxs("label", { children: [_jsx("span", { children: "Font size" }), _jsx("input", { type: "range", min: "13", max: "22", value: Number.parseInt(theme.fontSize, 10), onChange: (event) => updateTheme({ fontSize: `${event.target.value}px` }) })] }), _jsxs("label", { children: [_jsx("span", { children: "Font" }), _jsxs("select", { value: theme.fontFamily, onChange: (event) => updateTheme({ fontFamily: event.target.value }), children: [_jsx("option", { value: "inherit", children: "App default" }), _jsx("option", { value: "ui-serif, Georgia, Cambria, serif", children: "Serif" }), _jsx("option", { value: "ui-sans-serif, system-ui, sans-serif", children: "Sans" }), _jsx("option", { value: "ui-monospace, SFMono-Regular, Menlo, monospace", children: "Mono" })] })] }), _jsxs("label", { children: [_jsx("span", { children: "Line height" }), _jsx("input", { type: "range", min: "1.2", max: "2.2", step: "0.1", value: theme.lineHeight, onChange: (event) => updateTheme({ lineHeight: event.target.value }) })] }), _jsxs("label", { children: [_jsx("span", { children: "Padding" }), _jsx("input", { type: "range", min: "0", max: "32", value: Number.parseInt(theme.surfacePadding, 10), onChange: (event) => updateTheme({ surfacePadding: `${event.target.value}px` }) })] }), _jsxs("label", { children: [_jsx("span", { children: "Code radius" }), _jsx("input", { type: "range", min: "0", max: "16", value: Number.parseInt(theme.codeRadius, 10), onChange: (event) => updateTheme({ codeRadius: `${event.target.value}px` }) })] }), onReset ? (_jsx("button", { type: "button", onClick: onReset, children: "Reset style" })) : null] }));
@@ -14,7 +14,7 @@ export type MdKitEditorTheme = {
14
14
  mutedForeground: string;
15
15
  surfacePadding: string;
16
16
  };
17
- export type MdKitEditorThemeStyle = CSSProperties & Record<`--hsk-${string}`, string>;
17
+ export type MdKitEditorThemeStyle = CSSProperties & Record<`--mp-lb-mdkit-${string}`, string>;
18
18
  export declare const defaultMdKitEditorTheme: MdKitEditorTheme;
19
19
  export declare const darkMdKitEditorTheme: MdKitEditorTheme;
20
20
  export declare const createMdKitEditorThemeStyle: (theme: MdKitEditorTheme) => MdKitEditorThemeStyle;
@@ -29,19 +29,19 @@ export const darkMdKitEditorTheme = {
29
29
  surfacePadding: "1rem",
30
30
  };
31
31
  export const createMdKitEditorThemeStyle = (theme) => ({
32
- "--hsk-background": theme.background,
33
- "--hsk-block-gap": theme.blockGap,
34
- "--hsk-border": theme.border,
35
- "--hsk-code-background": theme.codeBackground,
36
- "--hsk-code-radius": theme.codeRadius,
37
- "--hsk-code-block-radius": theme.codeRadius,
38
- "--hsk-font-family": theme.fontFamily,
39
- "--hsk-font-size": theme.fontSize,
40
- "--hsk-foreground": theme.foreground,
41
- "--hsk-line-height": theme.lineHeight,
42
- "--hsk-link": theme.link,
43
- "--hsk-muted": theme.muted,
44
- "--hsk-muted-foreground": theme.mutedForeground,
45
- "--hsk-quote-border-color": theme.border,
46
- "--hsk-surface-padding": theme.surfacePadding,
32
+ "--mp-lb-mdkit-background": theme.background,
33
+ "--mp-lb-mdkit-block-gap": theme.blockGap,
34
+ "--mp-lb-mdkit-border": theme.border,
35
+ "--mp-lb-mdkit-code-background": theme.codeBackground,
36
+ "--mp-lb-mdkit-code-radius": theme.codeRadius,
37
+ "--mp-lb-mdkit-code-block-radius": theme.codeRadius,
38
+ "--mp-lb-mdkit-font-family": theme.fontFamily,
39
+ "--mp-lb-mdkit-font-size": theme.fontSize,
40
+ "--mp-lb-mdkit-foreground": theme.foreground,
41
+ "--mp-lb-mdkit-line-height": theme.lineHeight,
42
+ "--mp-lb-mdkit-link": theme.link,
43
+ "--mp-lb-mdkit-muted": theme.muted,
44
+ "--mp-lb-mdkit-muted-foreground": theme.mutedForeground,
45
+ "--mp-lb-mdkit-quote-border-color": theme.border,
46
+ "--mp-lb-mdkit-surface-padding": theme.surfacePadding,
47
47
  });
@@ -24,6 +24,6 @@ export const VersionHistoryPanel = ({ className, controller, onRestoreVersion, t
24
24
  setIsRestoring(false);
25
25
  }
26
26
  };
27
- return (_jsxs("aside", { className: joinClassNames("mdkit-version-history-panel", className), children: [_jsx("div", { className: "mdkit-version-history-header", children: _jsxs("div", { children: [_jsx("h2", { className: "mdkit-version-history-title", children: title }), _jsx("p", { className: "mdkit-version-history-subtitle", children: "Browse saved revisions and restore one when you need it." })] }) }), !controller.hasVersioning ? (_jsx("div", { className: "mdkit-version-history-empty", children: "This adapter does not expose version history." })) : null, controller.error ? (_jsx("div", { className: "mdkit-version-history-error", children: controller.error })) : null, controller.hasVersioning ? (_jsxs("div", { className: "mdkit-version-history-layout", children: [_jsx("div", { className: "mdkit-version-history-list", role: "list", children: controller.versions.length === 0 ? (_jsx("div", { className: "mdkit-version-history-empty", children: "No revisions have been recorded for this document yet." })) : (controller.versions.map((version) => (_jsxs("button", { type: "button", className: joinClassNames("mdkit-version-history-item", controller.selectedVersionId === version.id &&
28
- "mdkit-version-history-item-active"), onClick: () => void controller.openVersion(version.id), children: [_jsx("span", { className: "mdkit-version-history-item-title", children: getVersionLabel(version) }), _jsx("span", { className: "mdkit-version-history-item-meta", children: new Date(version.createdAt).toLocaleString() })] }, version.id)))) }), _jsx("div", { className: "mdkit-version-history-preview", children: controller.selectedVersion ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mdkit-version-history-preview-header", children: [_jsxs("div", { children: [_jsx("h3", { className: "mdkit-version-history-preview-title", children: getVersionLabel(controller.selectedVersion) }), _jsx("p", { className: "mdkit-version-history-item-meta", children: new Date(controller.selectedVersion.createdAt).toLocaleString() })] }), onRestoreVersion ? (_jsx("button", { type: "button", className: "mdkit-panel-primary-action", disabled: isRestoring, onClick: () => void restoreSelectedVersion(), children: isRestoring ? "Restoring..." : "Restore" })) : null] }), _jsx("pre", { className: "mdkit-version-history-code", children: controller.selectedVersion.content })] })) : (_jsx("div", { className: "mdkit-version-history-empty", children: "Select a saved revision to preview it here." })) })] })) : null, controller.isLoading ? (_jsx("div", { className: "mdkit-version-history-meta", children: "Loading version data..." })) : null] }));
27
+ return (_jsxs("aside", { className: joinClassNames("mp-lb-mdkit-version-history-panel", className), children: [_jsx("div", { className: "mp-lb-mdkit-version-history-header", children: _jsxs("div", { children: [_jsx("h2", { className: "mp-lb-mdkit-version-history-title", children: title }), _jsx("p", { className: "mp-lb-mdkit-version-history-subtitle", children: "Browse saved revisions and restore one when you need it." })] }) }), !controller.hasVersioning ? (_jsx("div", { className: "mp-lb-mdkit-version-history-empty", children: "This adapter does not expose version history." })) : null, controller.error ? (_jsx("div", { className: "mp-lb-mdkit-version-history-error", children: controller.error })) : null, controller.hasVersioning ? (_jsxs("div", { className: "mp-lb-mdkit-version-history-layout", children: [_jsx("div", { className: "mp-lb-mdkit-version-history-list", role: "list", children: controller.versions.length === 0 ? (_jsx("div", { className: "mp-lb-mdkit-version-history-empty", children: "No revisions have been recorded for this document yet." })) : (controller.versions.map((version) => (_jsxs("button", { type: "button", className: joinClassNames("mp-lb-mdkit-version-history-item", controller.selectedVersionId === version.id &&
28
+ "mp-lb-mdkit-version-history-item-active"), onClick: () => void controller.openVersion(version.id), children: [_jsx("span", { className: "mp-lb-mdkit-version-history-item-title", children: getVersionLabel(version) }), _jsx("span", { className: "mp-lb-mdkit-version-history-item-meta", children: new Date(version.createdAt).toLocaleString() })] }, version.id)))) }), _jsx("div", { className: "mp-lb-mdkit-version-history-preview", children: controller.selectedVersion ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mp-lb-mdkit-version-history-preview-header", children: [_jsxs("div", { children: [_jsx("h3", { className: "mp-lb-mdkit-version-history-preview-title", children: getVersionLabel(controller.selectedVersion) }), _jsx("p", { className: "mp-lb-mdkit-version-history-item-meta", children: new Date(controller.selectedVersion.createdAt).toLocaleString() })] }), onRestoreVersion ? (_jsx("button", { type: "button", className: "mp-lb-mdkit-panel-primary-action", disabled: isRestoring, onClick: () => void restoreSelectedVersion(), children: isRestoring ? "Restoring..." : "Restore" })) : null] }), _jsx("pre", { className: "mp-lb-mdkit-version-history-code", children: controller.selectedVersion.content })] })) : (_jsx("div", { className: "mp-lb-mdkit-version-history-empty", children: "Select a saved revision to preview it here." })) })] })) : null, controller.isLoading ? (_jsx("div", { className: "mp-lb-mdkit-version-history-meta", children: "Loading version data..." })) : null] }));
29
29
  };
package/docs/api.md CHANGED
@@ -51,7 +51,7 @@ end. Leave it off when the host application owns sizing and scrolling.
51
51
 
52
52
  The package stylesheet includes reset-resistant markdown rules for headings,
53
53
  lists, code blocks, blockquotes, and links. Styling is controlled with CSS
54
- variables on `.mdkit-markdown-editor`. See [Styling](./styling.md) for setup,
54
+ variables on `.mp-lb-mdkit-markdown-editor`. See [Styling](./styling.md) for setup,
55
55
  dark mode, fonts, sizing, and theme customization.
56
56
 
57
57
  ## Document Persistence
package/docs/shadcn.md CHANGED
@@ -107,7 +107,7 @@ If you do not use shadcn, use the base panels from the npm package:
107
107
  - `VersionHistoryPanel`
108
108
  - `MdKitConflictPanel`
109
109
 
110
- They render plain semantic HTML with stable `mdkit-*` classes. Import
110
+ They render plain semantic HTML with stable `mp-lb-mdkit-*` classes. Import
111
111
  `@mp-lb/mdkit/styles.css` for generic fallback styling, or
112
112
  replace the CSS entirely. See [Styling](./styling.md#component-styling).
113
113
 
package/docs/styling.md CHANGED
@@ -15,7 +15,7 @@ blockquotes, code blocks, spacing, and focus areas are left to your app's CSS.
15
15
 
16
16
  Many app frameworks include CSS resets. Tailwind Preflight, for example, removes
17
17
  default margins and list styling. The package stylesheet restores markdown
18
- editor defaults under `.mdkit-markdown-editor`, including:
18
+ editor defaults under `.mp-lb-mdkit-markdown-editor`, including:
19
19
 
20
20
  - heading sizes and spacing
21
21
  - paragraph spacing
@@ -65,21 +65,21 @@ can override them with a class:
65
65
 
66
66
  ```css
67
67
  .my-markdown-editor {
68
- --hsk-background: #ffffff;
69
- --hsk-foreground: #172033;
70
- --hsk-muted: #eef1f4;
71
- --hsk-muted-foreground: #5b6472;
72
- --hsk-border: #d8dee8;
73
- --hsk-link: #4f46e5;
74
- --hsk-font-family: Inter, system-ui, sans-serif;
75
- --hsk-font-size: 16px;
76
- --hsk-line-height: 1.7;
77
- --hsk-surface-padding: 1rem;
78
- --hsk-block-gap: 0.75rem;
79
- --hsk-list-item-gap: 0.125rem;
80
- --hsk-code-background: #eef1f4;
81
- --hsk-code-radius: 0.35rem;
82
- --hsk-code-block-radius: 0.75rem;
68
+ --mp-lb-mdkit-background: #ffffff;
69
+ --mp-lb-mdkit-foreground: #172033;
70
+ --mp-lb-mdkit-muted: #eef1f4;
71
+ --mp-lb-mdkit-muted-foreground: #5b6472;
72
+ --mp-lb-mdkit-border: #d8dee8;
73
+ --mp-lb-mdkit-link: #4f46e5;
74
+ --mp-lb-mdkit-font-family: Inter, system-ui, sans-serif;
75
+ --mp-lb-mdkit-font-size: 16px;
76
+ --mp-lb-mdkit-line-height: 1.7;
77
+ --mp-lb-mdkit-surface-padding: 1rem;
78
+ --mp-lb-mdkit-block-gap: 0.75rem;
79
+ --mp-lb-mdkit-list-item-gap: 0.125rem;
80
+ --mp-lb-mdkit-code-background: #eef1f4;
81
+ --mp-lb-mdkit-code-radius: 0.35rem;
82
+ --mp-lb-mdkit-code-block-radius: 0.75rem;
83
83
  }
84
84
  ```
85
85
 
@@ -97,9 +97,9 @@ runtime:
97
97
  ```tsx
98
98
  <MdKitEditor
99
99
  style={{
100
- "--hsk-font-family": "ui-serif, Georgia, serif",
101
- "--hsk-font-size": "18px",
102
- "--hsk-line-height": "1.8",
100
+ "--mp-lb-mdkit-font-family": "ui-serif, Georgia, serif",
101
+ "--mp-lb-mdkit-font-size": "18px",
102
+ "--mp-lb-mdkit-line-height": "1.8",
103
103
  }}
104
104
  value={markdown}
105
105
  onChange={setMarkdown}
@@ -109,21 +109,65 @@ runtime:
109
109
  See [`MdKitEditorProps`](./api.md#mdkiteditorprops) for the full component
110
110
  props.
111
111
 
112
- ## Component Styling
112
+ ## Class Hooks
113
113
 
114
- Editor styling and workflow component styling are separate.
114
+ The package uses stable `mp-lb-mdkit-*` class names for all package-owned
115
+ markup. These classes are a supported integration point for product-specific
116
+ styling. Prefer CSS variables for theme-level changes, and use class hooks when
117
+ you need structural changes, component-specific spacing, or state styling.
115
118
 
116
- `MdKitEditor` is styled through CSS variables on `.mdkit-markdown-editor`.
117
- Workflow panels such as `MdKitDocumentToolbar`, `MdKitConflictPanel`, and
118
- `VersionHistoryPanel` are intentionally design-system agnostic. They render raw
119
- semantic markup with stable `mdkit-*` class names. Without this stylesheet they
120
- are plain HTML; with this stylesheet they get generic fallback styling: square
121
- corners, one-pixel borders, clear spacing, and basic buttons.
119
+ ### Editor
122
120
 
123
- Style them in your app when you want them to match your product:
121
+ `MdKitEditor` renders the markdown editing surface and the selection bubble
122
+ toolbar.
123
+
124
+ - `.mp-lb-mdkit-markdown-editor`: root element rendered by `MdKitEditor`
125
+ - `.mp-lb-mdkit-markdown-editor-fill-height`: added to the root when
126
+ `fillHeight` is enabled
127
+ - `.mp-lb-mdkit-editor-shell`: internal editor layout wrapper
128
+ - `.mp-lb-mdkit-editor-surface`: scroll and background surface around the
129
+ ProseMirror editor
130
+ - `.mp-lb-mdkit-editor-empty`: loading or connecting placeholder
131
+ - `.mp-lb-mdkit-tiptap`: ProseMirror editable element
132
+ - `.mp-lb-mdkit-toolbar`: selection bubble toolbar
133
+ - `.mp-lb-mdkit-toolbar-button`: toolbar button
134
+ - `.mp-lb-mdkit-toolbar-button-active`: added to active toolbar buttons
135
+ - `.mp-lb-mdkit-toolbar-divider`: toolbar divider
136
+ - `.mp-lb-mdkit-collaboration-caret`: remote collaboration caret
137
+ - `.mp-lb-mdkit-collaboration-caret-label`: remote collaborator label
138
+
139
+ The editor root exposes `data-read-only="true"` when `readOnly` is enabled.
140
+
141
+ ### Theme Editor
142
+
143
+ `MdKitThemeEditor` renders controls for editing a theme object.
144
+
145
+ - `.mp-lb-mdkit-theme-editor`: root element rendered by `MdKitThemeEditor`
146
+
147
+ ### Document Toolbar
148
+
149
+ `MdKitDocumentToolbar` renders document save, restore, and conflict controls.
150
+
151
+ - `.mp-lb-mdkit-document-toolbar`: root element
152
+ - `.mp-lb-mdkit-document-toolbar-status`: status text group
153
+ - `.mp-lb-mdkit-document-toolbar-error`: non-conflict error message
154
+ - `.mp-lb-mdkit-document-toolbar-actions`: action button group
155
+ - `.mp-lb-mdkit-document-toolbar-conflict-trigger`: button that opens external
156
+ conflict UI
157
+ - `.mp-lb-mdkit-document-toolbar-conflict`: inline conflict action row
158
+
159
+ The root exposes these state attributes:
160
+
161
+ - `data-conflict`: `"true"` when a document conflict exists
162
+ - `data-dirty`: `"true"` when local edits are unsaved
163
+ - `data-save-status`: raw save status from the document controller
164
+ - `data-status`: display status normalized for CSS selectors, such as
165
+ `"saved"`, `"unsaved-changes"`, `"autosave-pending"`, or `"conflict"`
166
+
167
+ Example:
124
168
 
125
169
  ```css
126
- .mdkit-document-toolbar {
170
+ .mp-lb-mdkit-document-toolbar {
127
171
  display: flex;
128
172
  align-items: center;
129
173
  gap: 0.5rem;
@@ -131,42 +175,117 @@ Style them in your app when you want them to match your product:
131
175
  padding: 0.5rem 0;
132
176
  }
133
177
 
134
- .mdkit-document-toolbar-status,
135
- .mdkit-document-toolbar-actions,
136
- .mdkit-document-toolbar-conflict {
178
+ .mp-lb-mdkit-document-toolbar-status,
179
+ .mp-lb-mdkit-document-toolbar-actions,
180
+ .mp-lb-mdkit-document-toolbar-conflict {
137
181
  display: flex;
138
182
  align-items: center;
139
183
  gap: 0.5rem;
140
184
  }
141
185
 
142
- .mdkit-document-toolbar[data-conflict="true"] {
186
+ .mp-lb-mdkit-document-toolbar[data-conflict="true"] {
143
187
  color: #991b1b;
144
188
  }
145
189
  ```
146
190
 
147
- The toolbar class hooks are:
148
-
149
- - `.mdkit-document-toolbar`
150
- - `.mdkit-document-toolbar-status`
151
- - `.mdkit-document-toolbar-actions`
152
- - `.mdkit-document-toolbar-error`
153
- - `.mdkit-document-toolbar-conflict`
154
-
155
- It also exposes `data-conflict`, `data-dirty`, and `data-save-status`
156
- attributes for state-based styling.
157
-
158
- Version history and conflict panels use the same fallback panel CSS and expose:
159
-
160
- - `.mdkit-version-history-panel`
161
- - `.mdkit-version-history-header`
162
- - `.mdkit-version-history-list`
163
- - `.mdkit-version-history-item`
164
- - `.mdkit-version-history-preview`
165
- - `.mdkit-conflict-panel`
166
- - `.mdkit-conflict-panel-content`
167
- - `.mdkit-conflict-panel-action-row`
168
- - `.mdkit-panel-primary-action`
169
- - `.mdkit-panel-secondary-action`
191
+ ### Conflict Panel
192
+
193
+ `MdKitConflictPanel` renders conflict details, previews, and conflict actions.
194
+
195
+ - `.mp-lb-mdkit-conflict-panel`: root element
196
+ - `.mp-lb-mdkit-conflict-panel-content`: title, explanatory text, and metadata
197
+ - `.mp-lb-mdkit-conflict-panel-error`: error text
198
+ - `.mp-lb-mdkit-conflict-panel-meta`: remote version metadata
199
+ - `.mp-lb-mdkit-conflict-panel-preview`: preview area
200
+ - `.mp-lb-mdkit-conflict-panel-tabs`: preview tab list
201
+ - `.mp-lb-mdkit-conflict-panel-tab`: preview tab button
202
+ - `.mp-lb-mdkit-conflict-panel-tab-active`: active preview tab button
203
+ - `.mp-lb-mdkit-conflict-panel-action-row`: action button row
204
+ - `.mp-lb-mdkit-panel-secondary-action`: secondary panel action button
205
+
206
+ The preview tabs also use `aria-selected` for state-aware styling.
207
+
208
+ ### Version History Panel
209
+
210
+ `VersionHistoryPanel` renders a version list, selected version preview, restore
211
+ action, and empty/error states.
212
+
213
+ - `.mp-lb-mdkit-version-history-panel`: root element
214
+ - `.mp-lb-mdkit-version-history-header`: panel header
215
+ - `.mp-lb-mdkit-version-history-title`: panel title
216
+ - `.mp-lb-mdkit-version-history-subtitle`: panel subtitle
217
+ - `.mp-lb-mdkit-version-history-layout`: list and preview layout
218
+ - `.mp-lb-mdkit-version-history-list`: version list
219
+ - `.mp-lb-mdkit-version-history-item`: version list item button
220
+ - `.mp-lb-mdkit-version-history-item-active`: selected version list item
221
+ - `.mp-lb-mdkit-version-history-item-title`: list item title
222
+ - `.mp-lb-mdkit-version-history-item-meta`: list item or selected version metadata
223
+ - `.mp-lb-mdkit-version-history-preview`: selected version preview area
224
+ - `.mp-lb-mdkit-version-history-preview-header`: preview header
225
+ - `.mp-lb-mdkit-version-history-preview-title`: preview title
226
+ - `.mp-lb-mdkit-version-history-code`: markdown preview code block
227
+ - `.mp-lb-mdkit-version-history-empty`: empty state text
228
+ - `.mp-lb-mdkit-version-history-error`: error state text
229
+ - `.mp-lb-mdkit-version-history-meta`: footer metadata
230
+ - `.mp-lb-mdkit-panel-primary-action`: primary panel action button
231
+
232
+ ### Shared Panel Actions
233
+
234
+ Conflict and version panels share generic action classes:
235
+
236
+ - `.mp-lb-mdkit-panel-primary-action`: primary action button
237
+ - `.mp-lb-mdkit-panel-secondary-action`: secondary action button
238
+
239
+ ## CSS Variables
240
+
241
+ The package stylesheet defines variables on component roots so consumers can
242
+ override broad styling without depending on internal element structure.
243
+
244
+ ### Editor Variables
245
+
246
+ Set these on `.mp-lb-mdkit-markdown-editor`, a custom `className` passed to
247
+ `MdKitEditor`, or the inline `style` prop:
248
+
249
+ - `--mp-lb-mdkit-background`
250
+ - `--mp-lb-mdkit-foreground`
251
+ - `--mp-lb-mdkit-muted`
252
+ - `--mp-lb-mdkit-muted-foreground`
253
+ - `--mp-lb-mdkit-border`
254
+ - `--mp-lb-mdkit-accent`
255
+ - `--mp-lb-mdkit-accent-foreground`
256
+ - `--mp-lb-mdkit-link`
257
+ - `--mp-lb-mdkit-font-family`
258
+ - `--mp-lb-mdkit-font-size`
259
+ - `--mp-lb-mdkit-line-height`
260
+ - `--mp-lb-mdkit-surface-padding`
261
+ - `--mp-lb-mdkit-block-gap`
262
+ - `--mp-lb-mdkit-list-item-gap`
263
+ - `--mp-lb-mdkit-heading-font-weight`
264
+ - `--mp-lb-mdkit-heading-1-size`
265
+ - `--mp-lb-mdkit-heading-2-size`
266
+ - `--mp-lb-mdkit-code-background`
267
+ - `--mp-lb-mdkit-code-radius`
268
+ - `--mp-lb-mdkit-code-block-radius`
269
+ - `--mp-lb-mdkit-code-font-family`
270
+ - `--mp-lb-mdkit-quote-border-color`
271
+
272
+ ### Panel Variables
273
+
274
+ Set these on `.mp-lb-mdkit-document-toolbar`,
275
+ `.mp-lb-mdkit-conflict-panel`, `.mp-lb-mdkit-version-history-panel`, or a
276
+ wrapper around those components:
277
+
278
+ - `--mp-lb-mdkit-panel-background`
279
+ - `--mp-lb-mdkit-panel-surface`
280
+ - `--mp-lb-mdkit-panel-foreground`
281
+ - `--mp-lb-mdkit-panel-muted`
282
+ - `--mp-lb-mdkit-panel-muted-foreground`
283
+ - `--mp-lb-mdkit-panel-border`
284
+ - `--mp-lb-mdkit-panel-strong-border`
285
+ - `--mp-lb-mdkit-panel-danger`
286
+ - `--mp-lb-mdkit-panel-success`
287
+ - `--mp-lb-mdkit-panel-action-background`
288
+ - `--mp-lb-mdkit-panel-action-foreground`
170
289
 
171
290
  ## Theme Helpers
172
291
 
@@ -197,23 +316,23 @@ For class-based dark mode, scope variable overrides to your dark selector:
197
316
 
198
317
  ```css
199
318
  .my-markdown-editor {
200
- --hsk-background: #ffffff;
201
- --hsk-foreground: #172033;
202
- --hsk-muted: #eef1f4;
203
- --hsk-muted-foreground: #5b6472;
204
- --hsk-border: #d8dee8;
205
- --hsk-link: #4f46e5;
206
- --hsk-code-background: #eef1f4;
319
+ --mp-lb-mdkit-background: #ffffff;
320
+ --mp-lb-mdkit-foreground: #172033;
321
+ --mp-lb-mdkit-muted: #eef1f4;
322
+ --mp-lb-mdkit-muted-foreground: #5b6472;
323
+ --mp-lb-mdkit-border: #d8dee8;
324
+ --mp-lb-mdkit-link: #4f46e5;
325
+ --mp-lb-mdkit-code-background: #eef1f4;
207
326
  }
208
327
 
209
328
  .dark .my-markdown-editor {
210
- --hsk-background: #0b1220;
211
- --hsk-foreground: #e5edf7;
212
- --hsk-muted: #172033;
213
- --hsk-muted-foreground: #94a3b8;
214
- --hsk-border: #314158;
215
- --hsk-link: #38bdf8;
216
- --hsk-code-background: #111827;
329
+ --mp-lb-mdkit-background: #0b1220;
330
+ --mp-lb-mdkit-foreground: #e5edf7;
331
+ --mp-lb-mdkit-muted: #172033;
332
+ --mp-lb-mdkit-muted-foreground: #94a3b8;
333
+ --mp-lb-mdkit-border: #314158;
334
+ --mp-lb-mdkit-link: #38bdf8;
335
+ --mp-lb-mdkit-code-background: #111827;
217
336
  }
218
337
  ```
219
338
 
@@ -240,7 +359,7 @@ const style = createMdKitEditorThemeStyle(
240
359
  ## What Not To Customize First
241
360
 
242
361
  Prefer changing CSS variables before overriding internal selectors like
243
- `.hsk-tiptap p` or `.hsk-editor-surface`. Direct selector overrides are still an
362
+ `.mp-lb-mdkit-tiptap p` or `.mp-lb-mdkit-editor-surface`. Direct selector overrides are still an
244
363
  escape hatch, but they couple your app to mdkit's internal DOM.
245
364
 
246
365
  Use `MdKitThemeEditor` for theme builders, documentation, and debug tooling. It