@clevertask/scribe 0.0.15 → 0.1.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 (66) hide show
  1. package/README.md +77 -27
  2. package/dist/BarMenu-DaKIz3zZ.js +327 -0
  3. package/dist/assets/index.css +1 -1
  4. package/dist/components/Menu/BarMenu.d.ts +0 -1
  5. package/dist/components/Menu/BarMenu.d.ts.map +1 -1
  6. package/dist/components/Menu/BarMenu.js +8 -140
  7. package/dist/components/Menu/BubbleMenu.d.ts.map +1 -1
  8. package/dist/components/Menu/BubbleMenu.js +2074 -159
  9. package/dist/components/Menu/Mobile/ListOptionBar.d.ts.map +1 -1
  10. package/dist/components/Menu/Mobile/ListOptionBar.js +42 -22
  11. package/dist/components/Scribe/extension/emoji/EmojiList.d.ts +19 -1
  12. package/dist/components/Scribe/extension/emoji/EmojiList.d.ts.map +1 -1
  13. package/dist/components/Scribe/extension/emoji/EmojiList.js +42 -42
  14. package/dist/components/Scribe/extension/emoji/suggest.d.ts +2 -4
  15. package/dist/components/Scribe/extension/emoji/suggest.d.ts.map +1 -1
  16. package/dist/components/Scribe/extension/emoji/suggest.js +20 -15
  17. package/dist/components/Scribe/extension/extension-link.js +2 -984
  18. package/dist/components/Scribe/extension/extension-markdown-paste.js +4 -4
  19. package/dist/components/Scribe/extension/extension-selectedText.js +1 -1
  20. package/dist/components/Scribe/extension/getPopupMountTarget.d.ts +3 -0
  21. package/dist/components/Scribe/extension/getPopupMountTarget.d.ts.map +1 -0
  22. package/dist/components/Scribe/extension/getPopupMountTarget.js +16 -0
  23. package/dist/components/Scribe/extension/index.d.ts +16 -2
  24. package/dist/components/Scribe/extension/index.d.ts.map +1 -1
  25. package/dist/components/Scribe/extension/index.js +37122 -34
  26. package/dist/components/Scribe/extension/slashCommand/SlashCommandList.d.ts +4 -1
  27. package/dist/components/Scribe/extension/slashCommand/SlashCommandList.d.ts.map +1 -1
  28. package/dist/components/Scribe/extension/slashCommand/SlashCommandList.js +3730 -14
  29. package/dist/components/Scribe/extension/slashCommand/index.js +2 -2
  30. package/dist/components/Scribe/extension/slashCommand/renderItems.d.ts +1 -1
  31. package/dist/components/Scribe/extension/slashCommand/renderItems.d.ts.map +1 -1
  32. package/dist/components/Scribe/extension/slashCommand/renderItems.js +21 -16
  33. package/dist/components/Scribe/extension/tableOfContents.d.ts +48 -0
  34. package/dist/components/Scribe/extension/tableOfContents.d.ts.map +1 -0
  35. package/dist/components/Scribe/extension/tableOfContents.js +180 -0
  36. package/dist/components/Scribe/index.d.ts +12 -1
  37. package/dist/components/Scribe/index.d.ts.map +1 -1
  38. package/dist/components/Scribe/index.js +133 -87
  39. package/dist/extension-link-Ch_T7WWG.js +1030 -0
  40. package/dist/icons/ToolbarIcons.d.ts +19 -0
  41. package/dist/icons/ToolbarIcons.d.ts.map +1 -0
  42. package/dist/icons/ToolbarIcons.js +135 -0
  43. package/dist/{index-BKFDqQPh.js → index-BiBV5TQx.js} +6598 -5432
  44. package/dist/index-CqzMmrnw.js +1410 -0
  45. package/dist/index-DxF-1P4n.js +834 -0
  46. package/dist/index-V-gN11Y9.js +249 -0
  47. package/dist/main.css +200 -1123
  48. package/dist/main.js +1 -1
  49. package/dist/markdown-to-html-pL7ckd-m.js +1135 -0
  50. package/dist/purify.es-exIQuqhb.js +595 -0
  51. package/dist/tippy.esm-DLHdsnfG.js +1711 -0
  52. package/dist/utils/create-scribe-editor.d.ts +2 -2
  53. package/dist/utils/create-scribe-editor.d.ts.map +1 -1
  54. package/dist/utils/create-scribe-editor.js +3 -3
  55. package/dist/utils/html-to-markdown.d.ts.map +1 -1
  56. package/dist/utils/html-to-markdown.js +583 -18
  57. package/dist/utils/index.js +1 -1
  58. package/dist/utils/markdown-to-html.js +2 -2
  59. package/package.json +34 -37
  60. package/dist/clsx-OuTLNxxd.js +0 -16
  61. package/dist/index-CL2WLiGu.js +0 -159
  62. package/dist/index-Cxf4VEm1.js +0 -50957
  63. package/dist/index-PzbCrHp0.js +0 -2349
  64. package/dist/markdown-to-html-__93dwok.js +0 -1557
  65. package/dist/purify.es-BPDBzHtc.js +0 -552
  66. package/dist/turndown.browser.es-RmA_HBaI.js +0 -649
package/README.md CHANGED
@@ -9,12 +9,14 @@ A versatile, block-based rich text editor for diverse applications, built with T
9
9
  - **Markdown Paste:** Paste plain-text markdown into the editor and have it converted into rich content automatically.
10
10
  - **Versatile Integration:** Easily integrate `@clevertask/scribe` into any project requiring rich text editing.
11
11
  - **View and Edit:** Seamlessly switch between viewing and editing modes.
12
+ - **Experimental Table of Contents:** Subscribe to heading changes and render an app-owned table of contents outside the editor.
12
13
 
13
14
  ## Table of Contents
14
15
 
15
16
  - [@clevertask/scribe](#clevertaskscribe)
16
17
  - [Installation](#installation)
17
18
  - [Usage](#usage)
19
+ - [Experimental Table of Contents](#experimental-table-of-contents)
18
20
  - [Math Expressions](#math-expressions)
19
21
  - [Props](#props)
20
22
  - [Helper Functions](#helper-functions)
@@ -37,8 +39,10 @@ npm install @clevertask/scribe
37
39
  ### Basic usage
38
40
 
39
41
  ```tsx
42
+ import "@radix-ui/themes/styles.css";
40
43
  import "@clevertask/scribe/dist/main.css";
41
- import { Scribe, ScribeOnChangeContents } from "@clevertask/scribe";
44
+ import { Theme } from "@radix-ui/themes";
45
+ import { Scribe, ScribeRef } from "@clevertask/scribe";
42
46
 
43
47
  function App() {
44
48
  const onContentChange = useCallback(
@@ -48,14 +52,20 @@ function App() {
48
52
  [],
49
53
  );
50
54
 
51
- return <Scribe onContentChange={onContentChange} />;
55
+ return (
56
+ <Theme>
57
+ <Scribe onContentChange={onContentChange} />
58
+ </Theme>
59
+ );
52
60
  }
53
61
  ```
54
62
 
55
63
  ### With ref
56
64
 
57
65
  ```tsx
66
+ import "@radix-ui/themes/styles.css";
58
67
  import "@clevertask/scribe/dist/main.css";
68
+ import { Theme } from "@radix-ui/themes";
59
69
  import { Scribe, ScribeOnChangeContents } from "@clevertask/scribe";
60
70
 
61
71
  function App() {
@@ -67,37 +77,76 @@ function App() {
67
77
 
68
78
  return (
69
79
  <>
70
- <Scribe ref={editor} />
80
+ <Theme>
81
+ <Scribe ref={editor} />
82
+ </Theme>
71
83
  <button onClick={resetContent}>Reset content</button>
72
84
  </>
73
85
  );
74
86
  }
75
87
  ```
76
88
 
77
- ### With Dark Mode
89
+ ### Using Your App Theme
78
90
 
79
91
  ```tsx
92
+ import "@radix-ui/themes/styles.css";
80
93
  import "@clevertask/scribe/dist/main.css";
81
- import { Scribe, ScribeOnChangeContents } from "@clevertask/scribe";
94
+ import { Theme } from "@radix-ui/themes";
95
+ import { Scribe } from "@clevertask/scribe";
82
96
 
83
97
  function App() {
84
- const editor = useRef<ScribeRef>(null);
98
+ return (
99
+ <Theme appearance="dark">
100
+ <Scribe />
101
+ </Theme>
102
+ );
103
+ }
104
+ ```
85
105
 
86
- const resetContent = useCallback(() => {
87
- editor.current.resetContent();
88
- }, []);
106
+ ## Experimental Table of Contents
107
+
108
+ Scribe can expose table-of-contents data without rendering a table-of-contents block inside the editable document. Enable the experimental API with `enableTableOfContents`, keep the latest items in your app state, and call `scrollToTableOfContentsItem` when a user selects an entry.
109
+
110
+ ```tsx
111
+ import { Scribe, ScribeRef, ScribeTableOfContentsItem } from "@clevertask/scribe";
112
+ import { useRef, useState } from "react";
113
+
114
+ function DocumentEditor() {
115
+ const scribe = useRef<ScribeRef>(null);
116
+ const [tableOfContentsItems, setTableOfContentsItems] = useState<ScribeTableOfContentsItem[]>([]);
89
117
 
90
118
  return (
91
119
  <>
92
- <Scribe darkMode />
93
- <button onClick={resetContent}>Reset content</button>
120
+ <Scribe
121
+ ref={scribe}
122
+ enableTableOfContents
123
+ onTableOfContentsChange={setTableOfContentsItems}
124
+ />
125
+
126
+ {tableOfContentsItems.length > 0 ? (
127
+ <nav aria-label="Table of contents">
128
+ {tableOfContentsItems.map((item) => (
129
+ <button
130
+ key={item.id}
131
+ type="button"
132
+ onClick={() => scribe.current?.scrollToTableOfContentsItem(item)}
133
+ >
134
+ {item.textContent}
135
+ </button>
136
+ ))}
137
+ </nav>
138
+ ) : null}
94
139
  </>
95
140
  );
96
141
  }
97
142
  ```
98
143
 
144
+ The table of contents currently tracks default TipTap heading nodes only. Each item includes the heading text, depth, document position, DOM node, and active/scrolled state. This API is marked experimental while we validate the contract in real document surfaces.
145
+
99
146
  ## Math Expressions
100
147
 
148
+ Scribe's default UI is styled with Radix Themes components. Load `@radix-ui/themes/styles.css` once in your app alongside `@clevertask/scribe/dist/main.css`, and render Scribe somewhere inside a Radix `<Theme>`.
149
+
101
150
  Scribe ships with `@tiptap/extension-mathematics`. The extension renders math when it receives math nodes in the HTML:
102
151
 
103
152
  ```html
@@ -127,22 +176,23 @@ If your content arrives as HTML (for example from a server), use the helper belo
127
176
 
128
177
  ## Props
129
178
 
130
- | Prop | Type | Default | Description |
131
- | ------------------------ | -------------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
132
- | `content` | `string` | `undefined` | The initial content of the editor. This prop can also be used to control the editor's content. When `content` is updated, the editor's content will be updated accordingly. |
133
- | `onContentChange` | `(content: ScribeOnChangeContents) => void;` | `undefined` | A callback function triggered whenever the editor's content changes. It receives an object containing the current content in various formats (`jsonContent`, `htmlContent`, `markdownContent`). |
134
- | `editable` | `boolean` | `true` | Controls whether the editor is editable. |
135
- | `autoFocus` | `boolean` | `false` | Controls whether the editor should automatically focus when mounted. |
136
- | `extensions` | `Extension[]` | `undefined` | You can set your own extensions for the text editor. For more information, [check the tip tap extensions docs](https://tiptap.dev/docs/editor/core-concepts/extensions) |
137
- | `editorProps` | `EditorProps` | `undefined` | A tiptap-based prop to handle advanced use cases, you can read about it on their [documentation](https://tiptap.dev/docs/editor/api/editor#editorprops) |
138
- | `showBarMenu` | `boolean` | `true` | Determines whether to show the text editor top menu bar or not. This menu bar shows options to format the text |
139
- | `placeholderText` | `string` | `Type "/" for commands...` | Change the initial placeholder for your text editor |
140
- | `editorContentStyle` | `React.CSSProperties` | `undefined` | You can send a CSS object to add styles to the editor content container. Useful if you want to limit the editor's height. |
141
- | `editorContentClassName` | `string` | `undefined` | The same idea of `editorContentStyle` but with classes. |
142
- | `mainContainerStyle` | `React.CSSProperties` | `undefined` | You can send a CSS object to style the main editor container |
143
- | `mainContainerClassName` | `string` | `undefined` | The same idea of `mainContainerStyle` but with classes. |
144
- | `onKeyDown` | `KeyboardEventHandler` | `undefined` | A callback function that is triggered when a key is pressed within the editor. This allows you to handle custom keyboard shortcuts. For example, you can use this prop to implement a "send message" functionality when `Ctrl + Enter` is pressed. |
145
- | `darkMode` | `boolean` | `false` | You can switch the darkMode value to change the text editor's theme |
179
+ | Prop | Type | Default | Description |
180
+ | ------------------------- | ------------------------------------------------------------------ | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
181
+ | `content` | `string` | `undefined` | The initial content of the editor. Controlled updates through this prop are deprecated; prefer `ScribeRef.setContent` for programmatic updates after mount. |
182
+ | `onContentChange` | `(content: ScribeOnChangeContents) => void;` | `undefined` | A callback function triggered whenever the editor's content changes. It receives an object containing the current content in various formats (`jsonContent`, `htmlContent`, `markdownContent`). Internal table-of-contents metadata updates are ignored. |
183
+ | `editable` | `boolean` | `true` | Controls whether the editor is editable. |
184
+ | `autoFocus` | `boolean` | `false` | Controls whether the editor should automatically focus when mounted. |
185
+ | `extensions` | `Extension[]` | `undefined` | You can set your own extensions for the text editor. For more information, [check the tip tap extensions docs](https://tiptap.dev/docs/editor/core-concepts/extensions) |
186
+ | `editorProps` | `EditorProps` | `undefined` | A tiptap-based prop to handle advanced use cases, you can read about it on their [documentation](https://tiptap.dev/docs/editor/api/editor#editorprops) |
187
+ | `showBarMenu` | `boolean` | `true` | Determines whether to show the text editor top menu bar or not. This menu bar shows options to format the text |
188
+ | `placeholderText` | `string` | `Type "/" for commands...` | Change the initial placeholder for your text editor |
189
+ | `editorContentStyle` | `React.CSSProperties` | `undefined` | You can send a CSS object to add styles to the editor content container. Useful if you want to limit the editor's height. |
190
+ | `editorContentClassName` | `string` | `undefined` | The same idea of `editorContentStyle` but with classes. |
191
+ | `mainContainerStyle` | `React.CSSProperties` | `undefined` | You can send a CSS object to style the main editor container |
192
+ | `mainContainerClassName` | `string` | `undefined` | The same idea of `mainContainerStyle` but with classes. |
193
+ | `onKeyDown` | `KeyboardEventHandler` | `undefined` | A callback function that is triggered when a key is pressed within the editor. This allows you to handle custom keyboard shortcuts. For example, you can use this prop to implement a "send message" functionality when `Ctrl + Enter` is pressed. |
194
+ | `enableTableOfContents` | `boolean` | `false` | Experimental. Enables the app-owned table-of-contents API for heading nodes. |
195
+ | `onTableOfContentsChange` | `(items: ScribeTableOfContentsItem[], isCreate?: boolean) => void` | `undefined` | Experimental. Receives table-of-contents items whenever heading text, structure, or active/scrolled state changes. |
146
196
 
147
197
  ## Helper Functions
148
198
 
@@ -0,0 +1,327 @@
1
+ import { jsx as i, jsxs as l } from "react/jsx-runtime";
2
+ import { Box as A, Flex as r, Popover as g, IconButton as B, Text as m, TextField as R, Button as f, Separator as F } from "@radix-ui/themes";
3
+ import { u as H } from "./index-DxF-1P4n.js";
4
+ import { useState as v, useCallback as u, Fragment as U } from "react";
5
+ import { getPopupMountTarget as V } from "./components/Scribe/extension/getPopupMountTarget.js";
6
+ import { BoldIcon as q, ItalicIcon as E, StrikeIcon as W, InlineCodeIcon as Q, HighlightIcon as G, UnorderedListIcon as J, OrderedListIcon as K, LinkIcon as X, ImageIcon as Y, CodeBlockIcon as Z, BlockQuoteIcon as _, HorizontalLineIcon as ee } from "./icons/ToolbarIcons.js";
7
+ function O(e) {
8
+ var s, a, t = "";
9
+ if (typeof e == "string" || typeof e == "number") t += e;
10
+ else if (typeof e == "object") if (Array.isArray(e)) {
11
+ var h = e.length;
12
+ for (s = 0; s < h; s++) e[s] && (a = O(e[s])) && (t && (t += " "), t += a);
13
+ } else for (a in e) e[a] && (t && (t += " "), t += a);
14
+ return t;
15
+ }
16
+ function I() {
17
+ for (var e, s, a = 0, t = "", h = arguments.length; a < h; a++) (e = arguments[a]) && (s = O(e)) && (t && (t += " "), t += s);
18
+ return t;
19
+ }
20
+ const ce = ({ editor: e }) => {
21
+ const [s, a] = v(!1), [t, h] = v(!1), [p, y] = v(""), [b, L] = v(""), C = V(e), c = H({
22
+ editor: e,
23
+ selector: ({ editor: n }) => n ? {
24
+ isBold: n.isActive("bold"),
25
+ isItalic: n.isActive("italic"),
26
+ isStrike: n.isActive("strike"),
27
+ isCode: n.isActive("code"),
28
+ isHighlight: n.isActive("highlight"),
29
+ isBulletList: n.isActive("bulletList"),
30
+ isOrderedList: n.isActive("orderedList"),
31
+ isLink: n.isActive("link"),
32
+ isImage: n.isActive("image"),
33
+ isCodeBlock: n.isActive("codeBlock"),
34
+ isBlockquote: n.isActive("blockquote")
35
+ } : null
36
+ }), z = u(
37
+ (n) => {
38
+ if (n) {
39
+ const d = e.getAttributes("link").href ?? "";
40
+ y(d), h(!1);
41
+ }
42
+ a(n);
43
+ },
44
+ [e]
45
+ ), M = u(
46
+ (n) => {
47
+ if (n) {
48
+ const d = e.getAttributes("image").src ?? "";
49
+ L(d), a(!1);
50
+ }
51
+ h(n);
52
+ },
53
+ [e]
54
+ ), S = u(() => {
55
+ const n = p.trim();
56
+ if (n.length === 0) {
57
+ e.chain().focus().extendMarkRange("link").unsetLink().run(), a(!1);
58
+ return;
59
+ }
60
+ e.chain().focus().extendMarkRange("link").setLink({ href: n }).selectTextblockEnd().run(), a(!1);
61
+ }, [e, p]), P = u(() => {
62
+ e.chain().focus().extendMarkRange("link").unsetLink().run(), a(!1);
63
+ }, [e]), T = u(() => {
64
+ const n = b.trim();
65
+ n && (e.chain().focus().setImage({ src: n }).run(), h(!1));
66
+ }, [e, b]), D = u(
67
+ (n, d) => {
68
+ n.preventDefault(), d();
69
+ },
70
+ []
71
+ ), w = u((n) => {
72
+ n.preventDefault();
73
+ }, []), N = u(
74
+ ({ target: { value: n } }) => {
75
+ y(n);
76
+ },
77
+ []
78
+ ), $ = u(
79
+ ({ target: { value: n } }) => {
80
+ L(n);
81
+ },
82
+ []
83
+ ), x = [
84
+ [
85
+ {
86
+ name: "bold",
87
+ icon: q,
88
+ command: () => e.chain().focus().toggleBold().run(),
89
+ isActive: () => !!c?.isBold
90
+ },
91
+ {
92
+ name: "italic",
93
+ icon: E,
94
+ command: () => e.chain().focus().toggleItalic().run(),
95
+ isActive: () => !!c?.isItalic
96
+ },
97
+ {
98
+ name: "strike",
99
+ icon: W,
100
+ command: () => e.chain().focus().toggleStrike().run(),
101
+ isActive: () => !!c?.isStrike
102
+ }
103
+ ],
104
+ [
105
+ {
106
+ name: "inline-code",
107
+ icon: Q,
108
+ command: () => e.chain().focus().toggleCode().run(),
109
+ isActive: () => !!c?.isCode
110
+ },
111
+ {
112
+ name: "highlight",
113
+ icon: G,
114
+ command: () => e.chain().focus().toggleHighlight().run(),
115
+ isActive: () => !!c?.isHighlight
116
+ }
117
+ ],
118
+ [
119
+ {
120
+ name: "unordered-list",
121
+ icon: J,
122
+ command: () => e.chain().focus().toggleBulletList().run(),
123
+ isActive: () => !!c?.isBulletList
124
+ },
125
+ {
126
+ name: "ordered-list",
127
+ icon: K,
128
+ command: () => e.chain().focus().toggleOrderedList().run(),
129
+ isActive: () => !!c?.isOrderedList
130
+ }
131
+ ],
132
+ [
133
+ {
134
+ name: "link",
135
+ icon: X,
136
+ isActive: () => !!c?.isLink,
137
+ popover: "link"
138
+ },
139
+ {
140
+ name: "image",
141
+ icon: Y,
142
+ isActive: () => !!c?.isImage,
143
+ disabled: !1,
144
+ popover: "image"
145
+ },
146
+ {
147
+ name: "code-block",
148
+ icon: Z,
149
+ command: () => e.chain().focus().toggleCodeBlock().run(),
150
+ isActive: () => !!c?.isCodeBlock
151
+ },
152
+ {
153
+ name: "block-quote",
154
+ icon: _,
155
+ command: () => e.chain().focus().toggleBlockquote().run(),
156
+ isActive: () => !!c?.isBlockquote
157
+ },
158
+ {
159
+ name: "horizontal-line",
160
+ icon: ee,
161
+ command: () => e.chain().focus().setHorizontalRule().run(),
162
+ isActive: () => !1
163
+ }
164
+ ]
165
+ ];
166
+ return /* @__PURE__ */ i(A, { className: "scribe-toolbar", children: /* @__PURE__ */ i(r, { align: "center", gap: "3", wrap: "wrap", children: x.map((n, d) => /* @__PURE__ */ l(U, { children: [
167
+ /* @__PURE__ */ i(r, { align: "center", gap: "2", wrap: "wrap", children: n.map((o, k) => o.popover === "link" ? /* @__PURE__ */ l(
168
+ g.Root,
169
+ {
170
+ open: s,
171
+ onOpenChange: z,
172
+ children: [
173
+ /* @__PURE__ */ i(g.Trigger, { children: /* @__PURE__ */ i(
174
+ B,
175
+ {
176
+ type: "button",
177
+ radius: "medium",
178
+ color: "gray",
179
+ variant: o.isActive() ? "soft" : "ghost",
180
+ disabled: o.disabled || !e.isEditable,
181
+ title: o.name,
182
+ onMouseDown: w,
183
+ className: I(o.disabled && "scribe-toolbar-button--disabled"),
184
+ children: /* @__PURE__ */ i(o.icon, { className: "scribe-toolbar-icon" })
185
+ }
186
+ ) }),
187
+ /* @__PURE__ */ i(
188
+ g.Content,
189
+ {
190
+ container: C,
191
+ size: "2",
192
+ side: "bottom",
193
+ align: "start",
194
+ style: { maxWidth: "calc(100vw - 32px)", width: 320 },
195
+ children: /* @__PURE__ */ l(r, { direction: "column", gap: "4", children: [
196
+ /* @__PURE__ */ l(A, { children: [
197
+ /* @__PURE__ */ i(m, { as: "p", size: "3", weight: "medium", children: "Link" }),
198
+ /* @__PURE__ */ i(m, { as: "p", size: "2", color: "gray", children: "Add or update a link for the current selection." })
199
+ ] }),
200
+ /* @__PURE__ */ i("label", { children: /* @__PURE__ */ l(r, { direction: "column", gap: "2", children: [
201
+ /* @__PURE__ */ i(m, { as: "span", size: "2", weight: "medium", children: "URL" }),
202
+ /* @__PURE__ */ i(
203
+ R.Root,
204
+ {
205
+ autoFocus: !0,
206
+ placeholder: "https://example.com",
207
+ value: p,
208
+ onChange: N
209
+ }
210
+ )
211
+ ] }) }),
212
+ /* @__PURE__ */ l(r, { justify: "between", gap: "3", wrap: "wrap", children: [
213
+ /* @__PURE__ */ i(
214
+ f,
215
+ {
216
+ type: "button",
217
+ color: "red",
218
+ variant: "soft",
219
+ disabled: !((e.getAttributes("link").href ?? "").trim() || p.trim()),
220
+ onClick: P,
221
+ children: "Remove link"
222
+ }
223
+ ),
224
+ /* @__PURE__ */ l(r, { gap: "2", justify: "end", style: { marginLeft: "auto" }, children: [
225
+ /* @__PURE__ */ i(g.Close, { children: /* @__PURE__ */ i(f, { type: "button", variant: "soft", color: "gray", children: "Cancel" }) }),
226
+ /* @__PURE__ */ i(
227
+ f,
228
+ {
229
+ type: "button",
230
+ disabled: p.trim().length === 0,
231
+ onClick: S,
232
+ children: "Save"
233
+ }
234
+ )
235
+ ] })
236
+ ] })
237
+ ] })
238
+ }
239
+ )
240
+ ]
241
+ },
242
+ `${o.name}-${k}`
243
+ ) : o.popover === "image" ? /* @__PURE__ */ l(
244
+ g.Root,
245
+ {
246
+ open: t,
247
+ onOpenChange: M,
248
+ children: [
249
+ /* @__PURE__ */ i(g.Trigger, { children: /* @__PURE__ */ i(
250
+ B,
251
+ {
252
+ type: "button",
253
+ radius: "medium",
254
+ color: "gray",
255
+ variant: o.isActive() ? "soft" : "ghost",
256
+ disabled: o.disabled || !e.isEditable,
257
+ title: o.name,
258
+ onMouseDown: w,
259
+ className: I(o.disabled && "scribe-toolbar-button--disabled"),
260
+ children: /* @__PURE__ */ i(o.icon, { className: "scribe-toolbar-icon" })
261
+ }
262
+ ) }),
263
+ /* @__PURE__ */ i(
264
+ g.Content,
265
+ {
266
+ container: C,
267
+ size: "2",
268
+ side: "bottom",
269
+ align: "start",
270
+ style: { maxWidth: "calc(100vw - 32px)", width: 320 },
271
+ children: /* @__PURE__ */ l(r, { direction: "column", gap: "4", children: [
272
+ /* @__PURE__ */ l(A, { children: [
273
+ /* @__PURE__ */ i(m, { as: "p", size: "3", weight: "medium", children: "Image" }),
274
+ /* @__PURE__ */ i(m, { as: "p", size: "2", color: "gray", children: "Insert an image from a URL." })
275
+ ] }),
276
+ /* @__PURE__ */ i("label", { children: /* @__PURE__ */ l(r, { direction: "column", gap: "2", children: [
277
+ /* @__PURE__ */ i(m, { as: "span", size: "2", weight: "medium", children: "Image URL" }),
278
+ /* @__PURE__ */ i(
279
+ R.Root,
280
+ {
281
+ autoFocus: !0,
282
+ placeholder: "https://example.com/image.png",
283
+ value: b,
284
+ onChange: $
285
+ }
286
+ )
287
+ ] }) }),
288
+ /* @__PURE__ */ l(r, { justify: "end", gap: "2", children: [
289
+ /* @__PURE__ */ i(g.Close, { children: /* @__PURE__ */ i(f, { type: "button", variant: "soft", color: "gray", children: "Cancel" }) }),
290
+ /* @__PURE__ */ i(
291
+ f,
292
+ {
293
+ type: "button",
294
+ disabled: b.trim().length === 0,
295
+ onClick: T,
296
+ children: "Save"
297
+ }
298
+ )
299
+ ] })
300
+ ] })
301
+ }
302
+ )
303
+ ]
304
+ },
305
+ `${o.name}-${k}`
306
+ ) : /* @__PURE__ */ i(
307
+ B,
308
+ {
309
+ type: "button",
310
+ radius: "medium",
311
+ color: "gray",
312
+ variant: o.isActive() ? "soft" : "ghost",
313
+ disabled: o.disabled || !e.isEditable,
314
+ title: o.name,
315
+ onMouseDown: (j) => D(j, o.command),
316
+ className: I(o.disabled && "scribe-toolbar-button--disabled"),
317
+ children: /* @__PURE__ */ i(o.icon, { className: "scribe-toolbar-icon" })
318
+ },
319
+ `${o.name}-${k}`
320
+ )) }),
321
+ d !== x.length - 1 ? /* @__PURE__ */ i(F, { orientation: "vertical", decorative: !0, style: { height: 20 } }) : null
322
+ ] }, `format-group-${d}`)) }) });
323
+ };
324
+ export {
325
+ ce as B,
326
+ I as c
327
+ };