@fileverse-dev/ddoc 4.5.2 → 4.6.1-patch-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.
package/dist/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D as a, a as o, E as t, P as d, f as r, i, g as n, l as m, h as E, m as c, e as l, n as p, c as u, d as C, u as f, v as D } from "./index-wVRnXbOi.mjs";
1
+ import { D as a, a as o, E as t, P as d, f as r, i, g as n, j as m, h as E, m as c, e as l, l as p, c as u, d as C, u as f, v as D } from "./index-WbMw90L2.mjs";
2
2
  export {
3
3
  a as DdocEditor,
4
4
  o as DdocExportModal,
@@ -1,9 +1,9 @@
1
1
  var Vr = Object.defineProperty;
2
2
  var Wr = (t, e, O) => e in t ? Vr(t, e, { enumerable: !0, configurable: !0, writable: !0, value: O }) : t[e] = O;
3
3
  var gt = (t, e, O) => Wr(t, typeof e != "symbol" ? e + "" : e, O);
4
- import { j as Cr } from "./index-wVRnXbOi.mjs";
4
+ import { jsx as Cr } from "react/jsx-runtime";
5
5
  import { useRef as pe, useEffect as St } from "react";
6
- import { s as y, A as pO, T as dO, a as Gr, S as et, b as Lr, P as fO, E as j, i as QO, c as _, D as le, k as tt, F as Ar, M as Pt, W as Er, R as Ur, d as mO, N as oe, e as V, f as Mr, g as Ot, h as ce, p as $O, j as Y, t as h, l as Ir, I as rt, L as at, m as ye, n as ue, o as Qe, q as gO, r as te, u as SO, v as Br, w as Nr, x as PO, y as kO, z as Dr, B as Fr, C as Kr, G as Oe, H as ZO, J as Jr, K as kt, O as Hr, Q as ea, U as ta, V as Oa, X as ra, Y as aa, Z as ia, _ as sa, $ as na, a0 as la, a1 as oa, a2 as ca } from "./index-BuSMzCGL.mjs";
6
+ import { s as y, A as pO, T as dO, a as Gr, S as et, b as Lr, P as fO, E as j, i as QO, c as _, D as le, k as tt, F as Ar, M as Pt, W as Er, R as Ur, d as mO, N as oe, e as V, f as Mr, g as Ot, h as ce, p as $O, j as Y, t as h, l as Ir, I as rt, L as at, m as ye, n as ue, o as Qe, q as gO, r as te, u as SO, v as Br, w as Nr, x as PO, y as kO, z as Dr, B as Fr, C as Kr, G as Oe, H as ZO, J as Jr, K as kt, O as Hr, Q as ea, U as ta, V as Oa, X as ra, Y as aa, Z as ia, _ as sa, $ as na, a0 as la, a1 as oa, a2 as ca } from "./index-CbsbTEUv.mjs";
7
7
  class ua {
8
8
  /**
9
9
  Create a new completion context. (Mostly useful for testing
@@ -6062,7 +6062,7 @@ function tl({
6062
6062
  dO.addToHistory.of(!1)
6063
6063
  ]
6064
6064
  });
6065
- }, [t]), /* @__PURE__ */ Cr.jsx("div", { ref: r, className: "w-full h-full overflow-auto" });
6065
+ }, [t]), /* @__PURE__ */ Cr("div", { ref: r, className: "w-full h-full overflow-auto" });
6066
6066
  }
6067
6067
  export {
6068
6068
  tl as default
@@ -6,6 +6,8 @@ export interface AwarenessIdentity {
6
6
  isEns: string | boolean;
7
7
  }
8
8
  export declare const PLACEHOLDER_COLOR = "#9CA3AF";
9
+ export declare const COLLAB_PRESENCE_COLORS: readonly ["#30bced", "#6eeb83", "#fa69d1", "#ecd444", "#ee6352", "#db3041", "#0ad7f2", "#1bff39"];
9
10
  export declare function buildIdentityMap(states: Map<number, Record<string, unknown>>): Map<string, AwarenessIdentity>;
10
11
  export declare function mergePresence(roomMembers: string[], identityBySocketId: Map<string, AwarenessIdentity>): IDocCollabUsers[];
12
+ export declare function assignSessionColors(collaborators: IDocCollabUsers[], colorByName: Map<string, string>): IDocCollabUsers[];
11
13
  export declare function identitySignature(roomMembers: string[], identityBySocketId: Map<string, AwarenessIdentity>): string;
@@ -62,6 +62,7 @@ export declare class SocketClient {
62
62
  private roomId;
63
63
  roomMembers: string[];
64
64
  private _lastPresenceSignature;
65
+ private _presenceColorByName;
65
66
  private _onPresenceChange?;
66
67
  private _pendingAwarenessUpdates;
67
68
  private collaborationKeyPair;
@@ -0,0 +1,289 @@
1
+ import { jsx as m, jsxs as L } from "react/jsx-runtime";
2
+ import { useRef as D, useState as E, useEffect as A } from "react";
3
+ import { DynamicDropdown as P, Tooltip as O, IconButton as T } from "@fileverse/ui";
4
+ import { a3 as _, a4 as w, c as R } from "./index-CbsbTEUv.mjs";
5
+ const p = (e, n, o = n) => {
6
+ const { state: i } = e, l = i.changeByRange((t) => {
7
+ const d = i.sliceDoc(t.from, t.to), r = i.sliceDoc(
8
+ Math.max(0, t.from - n.length),
9
+ t.from
10
+ ), u = i.sliceDoc(
11
+ t.to,
12
+ Math.min(i.doc.length, t.to + o.length)
13
+ );
14
+ if (r === n && u === o)
15
+ return {
16
+ changes: [
17
+ { from: t.from - n.length, to: t.from, insert: "" },
18
+ { from: t.to, to: t.to + o.length, insert: "" }
19
+ ],
20
+ range: R.range(
21
+ t.from - n.length,
22
+ t.to - n.length
23
+ )
24
+ };
25
+ const b = n + d + o;
26
+ return {
27
+ changes: { from: t.from, to: t.to, insert: b },
28
+ range: R.range(
29
+ t.from + n.length,
30
+ t.from + n.length + d.length
31
+ )
32
+ };
33
+ });
34
+ e.dispatch(i.update(l, { scrollIntoView: !0 })), e.focus();
35
+ }, B = (e, n) => {
36
+ const { state: o } = e, i = [], l = /* @__PURE__ */ new Set();
37
+ for (const t of o.selection.ranges) {
38
+ let d = t.from;
39
+ for (; ; ) {
40
+ const r = o.doc.lineAt(d);
41
+ if (!l.has(r.number)) {
42
+ l.add(r.number);
43
+ const u = n(r.text, r.from);
44
+ u && i.push(u);
45
+ }
46
+ if (r.to >= t.to) break;
47
+ d = r.to + 1;
48
+ }
49
+ }
50
+ i.length && e.dispatch(o.update({ changes: i, scrollIntoView: !0 })), e.focus();
51
+ }, y = (e, n) => B(
52
+ e,
53
+ (o, i) => o.startsWith(n) ? { from: i, to: i + n.length, insert: "" } : { from: i, insert: n }
54
+ ), z = (e, n) => {
55
+ const o = "#".repeat(n) + " ";
56
+ return B(e, (i, l) => {
57
+ const t = i.match(/^(#{1,6})\s/);
58
+ return t && t[1].length === n ? { from: l, to: l + t[0].length, insert: "" } : t ? { from: l, to: l + t[0].length, insert: o } : { from: l, insert: o };
59
+ });
60
+ }, f = (e, n) => {
61
+ const { state: o } = e, i = o.selection.main, r = `${o.doc.lineAt(i.from).text.trim() === "" ? "" : `
62
+
63
+ `}${n}
64
+ `;
65
+ e.dispatch(
66
+ o.update({
67
+ changes: { from: i.from, insert: r },
68
+ selection: { anchor: i.from + r.length },
69
+ scrollIntoView: !0
70
+ })
71
+ ), e.focus();
72
+ }, G = (e, n) => {
73
+ const { state: o } = e, i = o.changeByRange((l) => {
74
+ const t = o.sliceDoc(l.from, l.to) || "text", d = n ?? "url", r = `[${t}](${d})`, u = l.from + 1 + t.length + 2;
75
+ return {
76
+ changes: { from: l.from, to: l.to, insert: r },
77
+ range: R.range(u, u + d.length)
78
+ };
79
+ });
80
+ e.dispatch(o.update(i, { scrollIntoView: !0 })), e.focus();
81
+ }, K = (e, n) => {
82
+ const o = `<img src="${n.src}" media-type="secure-img" encryptionKey="${n.encryptionKey}" nonce="${n.nonce}" ipfsUrl="${n.ipfsUrl}" ipfsHash="${n.ipfsHash}" version="2" authTag="${n.authTag}" mimeType="${n.mimeType}" />`;
83
+ f(e, o);
84
+ }, M = (e, n) => f(e, `<img src="${n}" media-type="img" />`), W = `| Column 1 | Column 2 |
85
+ | -------- | -------- |
86
+ | | |`, c = {
87
+ bold: (e) => p(e, "**"),
88
+ italic: (e) => p(e, "*"),
89
+ strike: (e) => p(e, "~~"),
90
+ inlineCode: (e) => p(e, "`"),
91
+ underline: (e) => p(e, "<u>", "</u>"),
92
+ heading: (e, n) => z(e, n),
93
+ bulletList: (e) => y(e, "- "),
94
+ orderedList: (e) => y(e, "1. "),
95
+ taskList: (e) => y(e, "- [ ] "),
96
+ blockquote: (e) => y(e, "> "),
97
+ codeBlock: (e) => f(e, "```\n\n```"),
98
+ horizontalRule: (e) => f(e, "---"),
99
+ table: (e) => f(e, W),
100
+ link: (e, n) => G(e, n),
101
+ undo: (e) => {
102
+ w(e), e.focus();
103
+ },
104
+ redo: (e) => {
105
+ _(e), e.focus();
106
+ },
107
+ // Highlight → inline HTML (round-trips via our turndown/DOMPurify rules).
108
+ highlight: (e, n) => n ? p(e, `<mark style="background-color: ${n}">`, "</mark>") : p(e, "<mark>", "</mark>")
109
+ }, H = [
110
+ [
111
+ { icon: "Undo", label: "Undo", run: (e) => c.undo(e) },
112
+ { icon: "Redo", label: "Redo", run: (e) => c.redo(e) }
113
+ ],
114
+ [
115
+ {
116
+ icon: "Heading1",
117
+ label: "Heading 1",
118
+ run: (e) => c.heading(e, 1)
119
+ },
120
+ {
121
+ icon: "Heading2",
122
+ label: "Heading 2",
123
+ run: (e) => c.heading(e, 2)
124
+ },
125
+ {
126
+ icon: "Heading3",
127
+ label: "Heading 3",
128
+ run: (e) => c.heading(e, 3)
129
+ }
130
+ ],
131
+ [
132
+ { icon: "Bold", label: "Bold", run: (e) => c.bold(e) },
133
+ { icon: "Italic", label: "Italic", run: (e) => c.italic(e) },
134
+ {
135
+ icon: "Underline",
136
+ label: "Underline",
137
+ run: (e) => c.underline(e)
138
+ },
139
+ {
140
+ icon: "Strikethrough",
141
+ label: "Strikethrough",
142
+ run: (e) => c.strike(e)
143
+ },
144
+ {
145
+ icon: "Code",
146
+ label: "Inline code",
147
+ run: (e) => c.inlineCode(e)
148
+ },
149
+ {
150
+ icon: "Highlighter",
151
+ label: "Highlight",
152
+ run: (e) => c.highlight(e)
153
+ }
154
+ ],
155
+ [
156
+ {
157
+ icon: "List",
158
+ label: "Bullet list",
159
+ run: (e) => c.bulletList(e)
160
+ },
161
+ {
162
+ icon: "ListOrdered",
163
+ label: "Numbered list",
164
+ run: (e) => c.orderedList(e)
165
+ },
166
+ {
167
+ icon: "ListChecks",
168
+ label: "To-do list",
169
+ run: (e) => c.taskList(e)
170
+ },
171
+ { icon: "TextQuote", label: "Quote", run: (e) => c.blockquote(e) }
172
+ ],
173
+ [
174
+ // Inserts [text](url) inline and selects `url` to type over.
175
+ { icon: "Link", label: "Link", run: (e) => c.link(e) },
176
+ { icon: "Image", label: "Image", run: () => {
177
+ }, upload: !0 },
178
+ {
179
+ icon: "Braces",
180
+ label: "Code block",
181
+ run: (e) => c.codeBlock(e)
182
+ },
183
+ { icon: "Table", label: "Table", run: (e) => c.table(e) },
184
+ {
185
+ icon: "Minus",
186
+ label: "Divider",
187
+ run: (e) => c.horizontalRule(e)
188
+ }
189
+ ]
190
+ ], $ = 3, V = H.slice(0, $), U = H.slice($), S = "!h-6 !w-6 !min-w-0", j = 560, C = () => /* @__PURE__ */ m("div", { className: "w-[1px] h-4 vertical-divider mx-1" });
191
+ function X({
192
+ view: e,
193
+ ipfsImageUploadFn: n,
194
+ onError: o
195
+ }) {
196
+ const i = (s) => {
197
+ const a = document.createElement("input");
198
+ a.type = "file", a.accept = "image/*", a.onchange = async () => {
199
+ var x;
200
+ const h = (x = a.files) == null ? void 0 : x[0];
201
+ if (!(!h || !h.type.includes("image/")))
202
+ try {
203
+ if (n) {
204
+ const g = await n(h);
205
+ K(s, {
206
+ src: URL.createObjectURL(h),
207
+ ipfsUrl: g.ipfsUrl,
208
+ encryptionKey: g.encryptionKey,
209
+ nonce: g.nonce,
210
+ ipfsHash: g.ipfsHash,
211
+ authTag: g.authTag,
212
+ mimeType: h.type
213
+ });
214
+ } else {
215
+ const g = await new Promise((I, N) => {
216
+ const k = new FileReader();
217
+ k.onload = () => I(k.result), k.onerror = N, k.readAsDataURL(h);
218
+ });
219
+ M(s, g);
220
+ }
221
+ } catch {
222
+ o == null || o("Failed to upload image");
223
+ }
224
+ }, a.click();
225
+ }, l = (s, a) => {
226
+ if (s.upload) {
227
+ i(a);
228
+ return;
229
+ }
230
+ s.run(a);
231
+ }, t = D(null), [d, r] = E(!1);
232
+ A(() => {
233
+ const s = t.current;
234
+ if (!s || typeof ResizeObserver > "u") return;
235
+ const a = () => r(s.clientWidth < j);
236
+ a();
237
+ const h = new ResizeObserver(a);
238
+ return h.observe(s), () => h.disconnect();
239
+ }, []);
240
+ const u = (s) => /* @__PURE__ */ m(O, { text: s.label, children: /* @__PURE__ */ m(
241
+ T,
242
+ {
243
+ variant: "ghost",
244
+ size: "sm",
245
+ className: S,
246
+ icon: s.icon,
247
+ disabled: !e,
248
+ onClick: () => e && l(s, e)
249
+ }
250
+ ) }, s.label), b = (s, a) => /* @__PURE__ */ L("div", { className: "flex items-center gap-0.5", children: [
251
+ a && /* @__PURE__ */ m(C, {}),
252
+ s.map(u)
253
+ ] }, s[0].label);
254
+ return /* @__PURE__ */ m("div", { className: "flex items-center px-2 py-2 border-b color-border-default shrink-0", children: /* @__PURE__ */ L(
255
+ "div",
256
+ {
257
+ ref: t,
258
+ className: "flex items-center gap-0.5 flex-1 min-w-0 overflow-hidden",
259
+ children: [
260
+ V.map((s, a) => b(s, a > 0)),
261
+ d ? /* @__PURE__ */ L("div", { className: "flex items-center gap-0.5", children: [
262
+ /* @__PURE__ */ m(C, {}),
263
+ /* @__PURE__ */ m(
264
+ P,
265
+ {
266
+ align: "start",
267
+ sideOffset: 8,
268
+ anchorTrigger: /* @__PURE__ */ m(O, { text: "More", children: /* @__PURE__ */ m(
269
+ T,
270
+ {
271
+ variant: "ghost",
272
+ size: "sm",
273
+ className: S,
274
+ icon: "Ellipsis",
275
+ disabled: !e
276
+ }
277
+ ) }),
278
+ content: /* @__PURE__ */ m("div", { className: "flex items-center gap-0.5 p-1", children: U.flat().map(u) })
279
+ },
280
+ "md-more-dropdown"
281
+ )
282
+ ] }) : U.map((s) => b(s, !0))
283
+ ]
284
+ }
285
+ ) });
286
+ }
287
+ export {
288
+ X as default
289
+ };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@fileverse-dev/ddoc",
3
3
  "private": false,
4
4
  "description": "DDoc",
5
- "version": "4.5.2",
5
+ "version": "4.6.1-patch-1",
6
6
  "main": "dist/index.es.js",
7
7
  "module": "dist/index.es.js",
8
8
  "exports": {
@@ -109,8 +109,6 @@
109
109
  "platform": "^1.3.6",
110
110
  "prosemirror-model": "^1.21.0",
111
111
  "prosemirror-state": "^1.4.3",
112
- "react": "^18.2.0",
113
- "react-dom": "^18.2.0",
114
112
  "react-tweet": "^3.2.2",
115
113
  "react-uuid": "^2.0.0",
116
114
  "react-window": "^2.2.7",
@@ -118,7 +116,7 @@
118
116
  "tailwindcss-animate": "^1.0.7",
119
117
  "tiptap-markdown": "^0.9.0",
120
118
  "turndown": "^7.2.0",
121
- "usehooks-ts": "^3.1.0",
119
+ "usehooks-ts": "^3.1.1",
122
120
  "uuid": "^10.0.0",
123
121
  "vaul": "^0.9.1",
124
122
  "vite-plugin-dts": "^3.6.3",
@@ -134,10 +132,12 @@
134
132
  "@dnd-kit/utilities": ">=3.2.2",
135
133
  "@fileverse/crypto": ">=0.0.21",
136
134
  "@fileverse/ens": "0.0.4",
137
- "@fileverse/ui": "5.2.3",
135
+ "@fileverse/ui": "5.3.1",
138
136
  "framer-motion": ">=11.2.10",
139
137
  "frimousse": ">=0.3.0",
140
138
  "mermaid": "11.14.0",
139
+ "react": "^18.2.0 || ^19.0.0",
140
+ "react-dom": "^18.2.0 || ^19.0.0",
141
141
  "viem": ">=2.35.0",
142
142
  "yjs": ">=13.6.30 <14"
143
143
  },
@@ -171,6 +171,8 @@
171
171
  "lint-staged": "^15.2.10",
172
172
  "postcss": "^8.4.38",
173
173
  "prettier": "^3.4.2",
174
+ "react": "^18.2.0",
175
+ "react-dom": "^18.2.0",
174
176
  "tailwindcss": "^3.4.3",
175
177
  "typescript": "^5.2.2",
176
178
  "vite": "^5.0.0",
@@ -1,289 +0,0 @@
1
- import { j as d } from "./index-wVRnXbOi.mjs";
2
- import { useRef as I, useState as N, useEffect as D } from "react";
3
- import { DynamicDropdown as E, Tooltip as R, IconButton as O } from "@fileverse/ui";
4
- import { a3 as A, a4 as P, c as y } from "./index-BuSMzCGL.mjs";
5
- const p = (e, t, o = t) => {
6
- const { state: s } = e, l = s.changeByRange((n) => {
7
- const u = s.sliceDoc(n.from, n.to), r = s.sliceDoc(
8
- Math.max(0, n.from - t.length),
9
- n.from
10
- ), m = s.sliceDoc(
11
- n.to,
12
- Math.min(s.doc.length, n.to + o.length)
13
- );
14
- if (r === t && m === o)
15
- return {
16
- changes: [
17
- { from: n.from - t.length, to: n.from, insert: "" },
18
- { from: n.to, to: n.to + o.length, insert: "" }
19
- ],
20
- range: y.range(
21
- n.from - t.length,
22
- n.to - t.length
23
- )
24
- };
25
- const b = t + u + o;
26
- return {
27
- changes: { from: n.from, to: n.to, insert: b },
28
- range: y.range(
29
- n.from + t.length,
30
- n.from + t.length + u.length
31
- )
32
- };
33
- });
34
- e.dispatch(s.update(l, { scrollIntoView: !0 })), e.focus();
35
- }, S = (e, t) => {
36
- const { state: o } = e, s = [], l = /* @__PURE__ */ new Set();
37
- for (const n of o.selection.ranges) {
38
- let u = n.from;
39
- for (; ; ) {
40
- const r = o.doc.lineAt(u);
41
- if (!l.has(r.number)) {
42
- l.add(r.number);
43
- const m = t(r.text, r.from);
44
- m && s.push(m);
45
- }
46
- if (r.to >= n.to) break;
47
- u = r.to + 1;
48
- }
49
- }
50
- s.length && e.dispatch(o.update({ changes: s, scrollIntoView: !0 })), e.focus();
51
- }, k = (e, t) => S(
52
- e,
53
- (o, s) => o.startsWith(t) ? { from: s, to: s + t.length, insert: "" } : { from: s, insert: t }
54
- ), _ = (e, t) => {
55
- const o = "#".repeat(t) + " ";
56
- return S(e, (s, l) => {
57
- const n = s.match(/^(#{1,6})\s/);
58
- return n && n[1].length === t ? { from: l, to: l + n[0].length, insert: "" } : n ? { from: l, to: l + n[0].length, insert: o } : { from: l, insert: o };
59
- });
60
- }, f = (e, t) => {
61
- const { state: o } = e, s = o.selection.main, r = `${o.doc.lineAt(s.from).text.trim() === "" ? "" : `
62
-
63
- `}${t}
64
- `;
65
- e.dispatch(
66
- o.update({
67
- changes: { from: s.from, insert: r },
68
- selection: { anchor: s.from + r.length },
69
- scrollIntoView: !0
70
- })
71
- ), e.focus();
72
- }, w = (e, t) => {
73
- const { state: o } = e, s = o.changeByRange((l) => {
74
- const n = o.sliceDoc(l.from, l.to) || "text", u = t ?? "url", r = `[${n}](${u})`, m = l.from + 1 + n.length + 2;
75
- return {
76
- changes: { from: l.from, to: l.to, insert: r },
77
- range: y.range(m, m + u.length)
78
- };
79
- });
80
- e.dispatch(o.update(s, { scrollIntoView: !0 })), e.focus();
81
- }, z = (e, t) => {
82
- const o = `<img src="${t.src}" media-type="secure-img" encryptionKey="${t.encryptionKey}" nonce="${t.nonce}" ipfsUrl="${t.ipfsUrl}" ipfsHash="${t.ipfsHash}" version="2" authTag="${t.authTag}" mimeType="${t.mimeType}" />`;
83
- f(e, o);
84
- }, G = (e, t) => f(e, `<img src="${t}" media-type="img" />`), K = `| Column 1 | Column 2 |
85
- | -------- | -------- |
86
- | | |`, c = {
87
- bold: (e) => p(e, "**"),
88
- italic: (e) => p(e, "*"),
89
- strike: (e) => p(e, "~~"),
90
- inlineCode: (e) => p(e, "`"),
91
- underline: (e) => p(e, "<u>", "</u>"),
92
- heading: (e, t) => _(e, t),
93
- bulletList: (e) => k(e, "- "),
94
- orderedList: (e) => k(e, "1. "),
95
- taskList: (e) => k(e, "- [ ] "),
96
- blockquote: (e) => k(e, "> "),
97
- codeBlock: (e) => f(e, "```\n\n```"),
98
- horizontalRule: (e) => f(e, "---"),
99
- table: (e) => f(e, K),
100
- link: (e, t) => w(e, t),
101
- undo: (e) => {
102
- P(e), e.focus();
103
- },
104
- redo: (e) => {
105
- A(e), e.focus();
106
- },
107
- // Highlight → inline HTML (round-trips via our turndown/DOMPurify rules).
108
- highlight: (e, t) => t ? p(e, `<mark style="background-color: ${t}">`, "</mark>") : p(e, "<mark>", "</mark>")
109
- }, C = [
110
- [
111
- { icon: "Undo", label: "Undo", run: (e) => c.undo(e) },
112
- { icon: "Redo", label: "Redo", run: (e) => c.redo(e) }
113
- ],
114
- [
115
- {
116
- icon: "Heading1",
117
- label: "Heading 1",
118
- run: (e) => c.heading(e, 1)
119
- },
120
- {
121
- icon: "Heading2",
122
- label: "Heading 2",
123
- run: (e) => c.heading(e, 2)
124
- },
125
- {
126
- icon: "Heading3",
127
- label: "Heading 3",
128
- run: (e) => c.heading(e, 3)
129
- }
130
- ],
131
- [
132
- { icon: "Bold", label: "Bold", run: (e) => c.bold(e) },
133
- { icon: "Italic", label: "Italic", run: (e) => c.italic(e) },
134
- {
135
- icon: "Underline",
136
- label: "Underline",
137
- run: (e) => c.underline(e)
138
- },
139
- {
140
- icon: "Strikethrough",
141
- label: "Strikethrough",
142
- run: (e) => c.strike(e)
143
- },
144
- {
145
- icon: "Code",
146
- label: "Inline code",
147
- run: (e) => c.inlineCode(e)
148
- },
149
- {
150
- icon: "Highlighter",
151
- label: "Highlight",
152
- run: (e) => c.highlight(e)
153
- }
154
- ],
155
- [
156
- {
157
- icon: "List",
158
- label: "Bullet list",
159
- run: (e) => c.bulletList(e)
160
- },
161
- {
162
- icon: "ListOrdered",
163
- label: "Numbered list",
164
- run: (e) => c.orderedList(e)
165
- },
166
- {
167
- icon: "ListChecks",
168
- label: "To-do list",
169
- run: (e) => c.taskList(e)
170
- },
171
- { icon: "TextQuote", label: "Quote", run: (e) => c.blockquote(e) }
172
- ],
173
- [
174
- // Inserts [text](url) inline and selects `url` to type over.
175
- { icon: "Link", label: "Link", run: (e) => c.link(e) },
176
- { icon: "Image", label: "Image", run: () => {
177
- }, upload: !0 },
178
- {
179
- icon: "Braces",
180
- label: "Code block",
181
- run: (e) => c.codeBlock(e)
182
- },
183
- { icon: "Table", label: "Table", run: (e) => c.table(e) },
184
- {
185
- icon: "Minus",
186
- label: "Divider",
187
- run: (e) => c.horizontalRule(e)
188
- }
189
- ]
190
- ], B = 3, M = C.slice(0, B), T = C.slice(B), U = "!h-6 !w-6 !min-w-0", W = 560, j = () => /* @__PURE__ */ d.jsx("div", { className: "w-[1px] h-4 vertical-divider mx-1" });
191
- function Q({
192
- view: e,
193
- ipfsImageUploadFn: t,
194
- onError: o
195
- }) {
196
- const s = (i) => {
197
- const a = document.createElement("input");
198
- a.type = "file", a.accept = "image/*", a.onchange = async () => {
199
- var L;
200
- const h = (L = a.files) == null ? void 0 : L[0];
201
- if (!(!h || !h.type.includes("image/")))
202
- try {
203
- if (t) {
204
- const g = await t(h);
205
- z(i, {
206
- src: URL.createObjectURL(h),
207
- ipfsUrl: g.ipfsUrl,
208
- encryptionKey: g.encryptionKey,
209
- nonce: g.nonce,
210
- ipfsHash: g.ipfsHash,
211
- authTag: g.authTag,
212
- mimeType: h.type
213
- });
214
- } else {
215
- const g = await new Promise((H, $) => {
216
- const x = new FileReader();
217
- x.onload = () => H(x.result), x.onerror = $, x.readAsDataURL(h);
218
- });
219
- G(i, g);
220
- }
221
- } catch {
222
- o == null || o("Failed to upload image");
223
- }
224
- }, a.click();
225
- }, l = (i, a) => {
226
- if (i.upload) {
227
- s(a);
228
- return;
229
- }
230
- i.run(a);
231
- }, n = I(null), [u, r] = N(!1);
232
- D(() => {
233
- const i = n.current;
234
- if (!i || typeof ResizeObserver > "u") return;
235
- const a = () => r(i.clientWidth < W);
236
- a();
237
- const h = new ResizeObserver(a);
238
- return h.observe(i), () => h.disconnect();
239
- }, []);
240
- const m = (i) => /* @__PURE__ */ d.jsx(R, { text: i.label, children: /* @__PURE__ */ d.jsx(
241
- O,
242
- {
243
- variant: "ghost",
244
- size: "sm",
245
- className: U,
246
- icon: i.icon,
247
- disabled: !e,
248
- onClick: () => e && l(i, e)
249
- }
250
- ) }, i.label), b = (i, a) => /* @__PURE__ */ d.jsxs("div", { className: "flex items-center gap-0.5", children: [
251
- a && /* @__PURE__ */ d.jsx(j, {}),
252
- i.map(m)
253
- ] }, i[0].label);
254
- return /* @__PURE__ */ d.jsx("div", { className: "flex items-center px-2 py-2 border-b color-border-default shrink-0", children: /* @__PURE__ */ d.jsxs(
255
- "div",
256
- {
257
- ref: n,
258
- className: "flex items-center gap-0.5 flex-1 min-w-0 overflow-hidden",
259
- children: [
260
- M.map((i, a) => b(i, a > 0)),
261
- u ? /* @__PURE__ */ d.jsxs("div", { className: "flex items-center gap-0.5", children: [
262
- /* @__PURE__ */ d.jsx(j, {}),
263
- /* @__PURE__ */ d.jsx(
264
- E,
265
- {
266
- align: "start",
267
- sideOffset: 8,
268
- anchorTrigger: /* @__PURE__ */ d.jsx(R, { text: "More", children: /* @__PURE__ */ d.jsx(
269
- O,
270
- {
271
- variant: "ghost",
272
- size: "sm",
273
- className: U,
274
- icon: "Ellipsis",
275
- disabled: !e
276
- }
277
- ) }),
278
- content: /* @__PURE__ */ d.jsx("div", { className: "flex items-center gap-0.5 p-1", children: T.flat().map(m) })
279
- },
280
- "md-more-dropdown"
281
- )
282
- ] }) : T.map((i) => b(i, !0))
283
- ]
284
- }
285
- ) });
286
- }
287
- export {
288
- Q as default
289
- };