@dxos/react-ui-editor 0.3.11-next.ee2b64c → 0.4.0

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 (25) hide show
  1. package/dist/lib/browser/index.mjs +1178 -159
  2. package/dist/lib/browser/index.mjs.map +3 -3
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  5. package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/Toolbar/Toolbar.d.ts +8 -4
  7. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  8. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +5 -3
  9. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  10. package/dist/types/src/extensions/comments.d.ts +5 -1
  11. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  12. package/dist/types/src/extensions/markdown/formatting.d.ts +55 -10
  13. package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
  14. package/dist/types/src/extensions/markdown/formatting.test.d.ts +3 -0
  15. package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +1 -0
  16. package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
  17. package/package.json +24 -24
  18. package/src/components/TextEditor/MarkdownEditor.stories.tsx +3 -3
  19. package/src/components/TextEditor/hooks.stories.tsx +6 -1
  20. package/src/components/Toolbar/Toolbar.stories.tsx +16 -4
  21. package/src/components/Toolbar/Toolbar.tsx +128 -30
  22. package/src/extensions/comments.ts +2 -2
  23. package/src/extensions/markdown/formatting.test.ts +482 -0
  24. package/src/extensions/markdown/formatting.ts +1118 -69
  25. package/src/hooks/useActionHandler.ts +47 -16
@@ -8,10 +8,10 @@ import { tags as tags2 } from "@lezer/highlight";
8
8
 
9
9
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
10
10
  import { EditorState as EditorState2 } from "@codemirror/state";
11
- import { EditorView as EditorView13 } from "@codemirror/view";
11
+ import { EditorView as EditorView14 } from "@codemirror/view";
12
12
  import { vim } from "@replit/codemirror-vim";
13
13
  import defaultsDeep2 from "lodash.defaultsdeep";
14
- import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
14
+ import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2 } from "react";
15
15
  import { log as log2 } from "@dxos/log";
16
16
  import { useThemeContext } from "@dxos/react-ui";
17
17
  import { focusRing, mx as mx3 } from "@dxos/react-ui-theme";
@@ -1301,7 +1301,11 @@ var createComment = (view) => {
1301
1301
  to
1302
1302
  });
1303
1303
  if (cursor) {
1304
- const id = options.onCreate?.(cursor, view.coordsAtPos(from));
1304
+ const id = options.onCreate?.({
1305
+ cursor,
1306
+ from,
1307
+ location: view.coordsAtPos(from)
1308
+ });
1305
1309
  if (id) {
1306
1310
  view.dispatch({
1307
1311
  effects: setSelection.of({
@@ -1829,89 +1833,836 @@ var code2 = () => {
1829
1833
  // packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
1830
1834
  import { snippet } from "@codemirror/autocomplete";
1831
1835
  import { syntaxTree as syntaxTree2 } from "@codemirror/language";
1832
- import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
1833
- import { Decoration as Decoration4, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
1834
- var setHeading = (level) => (view) => {
1835
- const { selection: { ranges }, doc } = view.state;
1836
+ import { RangeSetBuilder as RangeSetBuilder2, EditorSelection } from "@codemirror/state";
1837
+ import { Decoration as Decoration4, EditorView as EditorView9, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
1838
+ import { useState, useMemo } from "react";
1839
+ var compareFormatting = (a, b) => a.blockType === b.blockType && a.strong === b.strong && a.emphasis === b.emphasis && a.strikethrough === b.strikethrough && a.code === b.code && a.link === b.link && a.listStyle === b.listStyle && a.blockQuote === b.blockQuote;
1840
+ var Inline;
1841
+ (function(Inline2) {
1842
+ Inline2[Inline2["Strong"] = 0] = "Strong";
1843
+ Inline2[Inline2["Emphasis"] = 1] = "Emphasis";
1844
+ Inline2[Inline2["Strikethrough"] = 2] = "Strikethrough";
1845
+ Inline2[Inline2["Code"] = 3] = "Code";
1846
+ })(Inline || (Inline = {}));
1847
+ var List;
1848
+ (function(List2) {
1849
+ List2[List2["Ordered"] = 0] = "Ordered";
1850
+ List2[List2["Bullet"] = 1] = "Bullet";
1851
+ List2[List2["Task"] = 2] = "Task";
1852
+ })(List || (List = {}));
1853
+ var setHeading = (level) => ({ state, dispatch }) => {
1854
+ const { selection: { ranges }, doc } = state;
1836
1855
  const changes = [];
1856
+ let prevBlock = -1;
1837
1857
  for (const range of ranges) {
1838
- const { number } = doc.lineAt(range.anchor);
1839
- const { from, to } = doc.line(number);
1840
- const line = doc.sliceString(from, to);
1841
- const [_, marks, spaces] = line.match(/(#+)(\s+)/) ?? [];
1842
- const current = marks?.length ?? 0;
1843
- if (level !== current) {
1844
- changes.push({
1845
- from,
1846
- to: from + current + (spaces?.length ?? 0),
1847
- insert: "#".repeat(level) + (level > 0 ? " " : "")
1848
- });
1849
- }
1850
- }
1851
- if (changes.length) {
1852
- view.dispatch({
1853
- changes
1858
+ syntaxTree2(state).iterate({
1859
+ from: range.from,
1860
+ to: range.to,
1861
+ enter: (node) => {
1862
+ if (!Object.hasOwn(Textblocks, node.name) || prevBlock === node.from) {
1863
+ return;
1864
+ }
1865
+ prevBlock = node.from;
1866
+ const blockType = Textblocks[node.name];
1867
+ const isHeading = /heading(\d)/.exec(blockType);
1868
+ const curLevel = isHeading ? +isHeading[1] : node.name === "Paragraph" ? 0 : -1;
1869
+ if (curLevel < 0 || curLevel === level) {
1870
+ return;
1871
+ }
1872
+ if (curLevel === 0) {
1873
+ changes.push({
1874
+ from: node.from,
1875
+ insert: "#".repeat(level) + " "
1876
+ });
1877
+ } else if (node.name === "SetextHeading1" || node.name === "SetextHeading2") {
1878
+ const nextLine = doc.lineAt(node.to);
1879
+ if (level) {
1880
+ changes.push({
1881
+ from: node.from,
1882
+ insert: "#".repeat(level) + " "
1883
+ });
1884
+ }
1885
+ changes.push({
1886
+ from: nextLine.from - 1,
1887
+ to: nextLine.to
1888
+ });
1889
+ } else {
1890
+ if (level === 0) {
1891
+ changes.push({
1892
+ from: node.from,
1893
+ to: Math.min(node.to, node.from + curLevel + 1)
1894
+ });
1895
+ } else if (level < curLevel) {
1896
+ changes.push({
1897
+ from: node.from,
1898
+ to: node.from + (curLevel - level)
1899
+ });
1900
+ } else {
1901
+ changes.push({
1902
+ from: node.from,
1903
+ insert: "#".repeat(level - curLevel)
1904
+ });
1905
+ }
1906
+ }
1907
+ }
1854
1908
  });
1855
1909
  }
1910
+ if (!changes.length) {
1911
+ return false;
1912
+ }
1913
+ dispatch(state.update({
1914
+ changes,
1915
+ userEvent: "format.setHeading",
1916
+ scrollIntoView: true
1917
+ }));
1856
1918
  return true;
1857
1919
  };
1858
- var toggleStyle = (mark2) => (view) => {
1859
- const { ranges } = view.state.selection;
1860
- for (const range of ranges) {
1861
- if (range.from === range.to) {
1862
- return false;
1920
+ var setStyle = (type, enable) => ({ state, dispatch }) => {
1921
+ const marker = inlineMarkerText(type);
1922
+ const changes = state.changeByRange((range) => {
1923
+ if (!enable && range.empty) {
1924
+ const after = state.doc.sliceString(range.head, range.head + 6);
1925
+ const found = after.indexOf(marker);
1926
+ if (found >= 0 && /^[*~`]*$/.test(after.slice(0, found))) {
1927
+ const before = state.doc.sliceString(range.head - 6, range.head);
1928
+ if (before.slice(before.length - found - marker.length, before.length - found) === marker && [
1929
+ ...before.slice(before.length - found)
1930
+ ].reverse().join("") === after.slice(0, found)) {
1931
+ return {
1932
+ changes: [
1933
+ {
1934
+ from: range.head - marker.length - found,
1935
+ to: range.head - found
1936
+ },
1937
+ {
1938
+ from: range.head + found,
1939
+ to: range.head + found + marker.length
1940
+ }
1941
+ ],
1942
+ range: EditorSelection.cursor(range.from - marker.length)
1943
+ };
1944
+ }
1945
+ }
1863
1946
  }
1864
- view.dispatch({
1865
- changes: [
1866
- {
1867
- from: range.from,
1868
- insert: mark2
1869
- },
1870
- {
1871
- from: range.to,
1872
- insert: mark2
1947
+ const changes2 = [];
1948
+ const changesAtEnd = [];
1949
+ let blockStart = -1;
1950
+ let blockEnd = -1;
1951
+ let startCovered = false;
1952
+ let endCovered = false;
1953
+ let { from, to } = range;
1954
+ syntaxTree2(state).iterate({
1955
+ from,
1956
+ to,
1957
+ enter: (node) => {
1958
+ const { name } = node;
1959
+ if (Object.hasOwn(Textblocks, name) && Textblocks[name] !== "codeblock") {
1960
+ blockStart = blockContentStart(node);
1961
+ blockEnd = blockContentEnd(node, state.doc);
1962
+ startCovered = endCovered = false;
1963
+ } else if (name === "Link" || name === "Image" && enable) {
1964
+ if (from < node.from && to > node.from && to <= node.to) {
1965
+ to = node.to;
1966
+ } else if (to > node.to && from >= node.from && from < node.to) {
1967
+ from = node.from;
1968
+ }
1969
+ } else if (IgnoreInline.has(name) && enable) {
1970
+ if (node.from < from && node.to > from) {
1971
+ if (to === from) {
1972
+ to = node.to;
1973
+ }
1974
+ from = node.to;
1975
+ }
1976
+ if (node.from < to && node.to > to) {
1977
+ to = node.from;
1978
+ }
1979
+ } else if (Object.hasOwn(InlineMarker, name)) {
1980
+ const markType = InlineMarker[name];
1981
+ const size = inlineMarkerText(markType).length;
1982
+ const openEnd = node.from + size;
1983
+ const closeStart = node.to - size;
1984
+ if (markType === type) {
1985
+ if (openEnd <= from && closeStart >= from) {
1986
+ startCovered = openEnd === from ? "adjacent" : true;
1987
+ }
1988
+ if (openEnd <= to && closeStart >= to) {
1989
+ endCovered = closeStart === to ? "adjacent" : true;
1990
+ }
1991
+ }
1992
+ if (markType === type || type === 3 && enable) {
1993
+ if (node.from >= from && openEnd <= to) {
1994
+ changes2.push({
1995
+ from: node.from,
1996
+ to: openEnd
1997
+ });
1998
+ if (markType !== type && closeStart >= to) {
1999
+ changesAtEnd.push({
2000
+ from: skipSpaces(Math.min(to, blockEnd), state.doc, 1, blockEnd),
2001
+ insert: inlineMarkerText(markType)
2002
+ });
2003
+ }
2004
+ }
2005
+ if (closeStart >= from && node.to <= to) {
2006
+ changes2.push({
2007
+ from: closeStart,
2008
+ to: node.to
2009
+ });
2010
+ if (markType !== type && openEnd <= from) {
2011
+ changes2.push({
2012
+ from: skipSpaces(Math.max(from, blockStart), state.doc, -1, blockStart),
2013
+ insert: inlineMarkerText(markType)
2014
+ });
2015
+ }
2016
+ }
2017
+ }
1873
2018
  }
1874
- ]
2019
+ },
2020
+ leave: (node) => {
2021
+ if (Object.hasOwn(Textblocks, node.name) && Textblocks[node.name] !== "codeblock") {
2022
+ const rangeStart = Math.max(from, blockStart);
2023
+ const rangeEnd = Math.min(to, blockEnd);
2024
+ if (enable) {
2025
+ if (!startCovered) {
2026
+ changes2.push({
2027
+ from: rangeStart,
2028
+ insert: marker
2029
+ });
2030
+ }
2031
+ if (!endCovered) {
2032
+ changes2.push({
2033
+ from: rangeEnd,
2034
+ insert: marker
2035
+ });
2036
+ }
2037
+ } else {
2038
+ if (startCovered === "adjacent") {
2039
+ changes2.push({
2040
+ from: from - marker.length,
2041
+ to: from
2042
+ });
2043
+ } else if (startCovered) {
2044
+ changes2.push({
2045
+ from: skipSpaces(rangeStart, state.doc, -1, blockStart),
2046
+ insert: marker
2047
+ });
2048
+ }
2049
+ if (endCovered === "adjacent") {
2050
+ changes2.push({
2051
+ from: to,
2052
+ to: to + marker.length
2053
+ });
2054
+ } else if (endCovered) {
2055
+ changes2.push({
2056
+ from: skipSpaces(rangeEnd, state.doc, 1, blockEnd),
2057
+ insert: marker
2058
+ });
2059
+ }
2060
+ }
2061
+ }
2062
+ }
1875
2063
  });
1876
- }
2064
+ const changeSet = state.changes(changes2.concat(changesAtEnd));
2065
+ return {
2066
+ changes: changeSet,
2067
+ range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
2068
+ };
2069
+ });
2070
+ dispatch(state.update(changes, {
2071
+ userEvent: enable ? "format.style.add" : "format.style.remove",
2072
+ scrollIntoView: true
2073
+ }));
1877
2074
  return true;
1878
2075
  };
2076
+ var addStyle = (style) => setStyle(style, true);
2077
+ var removeStyle = (style) => setStyle(style, false);
2078
+ var toggleStyle = (style) => (arg) => {
2079
+ const form = getFormatting(arg.state);
2080
+ return setStyle(style, style === 0 ? !form.strong : style === 1 ? !form.emphasis : style === 2 ? !form.strikethrough : !form.code)(arg);
2081
+ };
2082
+ var toggleStrong = toggleStyle(0);
2083
+ var toggleEmphasis = toggleStyle(1);
2084
+ var toggleStrikethrough = toggleStyle(2);
2085
+ var toggleInlineCode = toggleStyle(3);
2086
+ var inlineMarkerText = (type) => type === 0 ? "**" : type === 2 ? "~~" : type === 1 ? "*" : "`";
2087
+ var blockContentStart = (node) => {
2088
+ const atx = /^ATXHeading(\d)/.exec(node.name);
2089
+ if (atx) {
2090
+ return Math.min(node.to, node.from + +atx[1] + 1);
2091
+ }
2092
+ return node.from;
2093
+ };
2094
+ var blockContentEnd = (node, doc) => {
2095
+ const setext = /^SetextHeading(\d)/.exec(node.name);
2096
+ const lastLine = doc.lineAt(node.to);
2097
+ if (setext || /^[\s>]*$/.exec(lastLine.text)) {
2098
+ return lastLine.from - 1;
2099
+ }
2100
+ return node.to;
2101
+ };
2102
+ var skipSpaces = (pos, doc, dir, limit) => {
2103
+ const line = doc.lineAt(pos);
2104
+ while (pos !== limit && line.text[pos - line.from - (dir < 0 ? 1 : 0)] === " ") {
2105
+ pos += dir;
2106
+ }
2107
+ return pos;
2108
+ };
1879
2109
  var snippets = {
1880
2110
  codeblock: snippet([
1881
- "```#{lang}",
1882
- " #{}",
2111
+ //
2112
+ "```#{}",
2113
+ "#{}",
1883
2114
  "```"
1884
2115
  ].join("\n")),
1885
2116
  table: snippet([
2117
+ //
1886
2118
  "| #{col1} | #{col2} |",
1887
2119
  "| ---- | ---- |",
1888
2120
  "| #{val1} | #{val2} |",
1889
- "| #{val3} | #{val4} |"
2121
+ "| #{val3} | #{val4} |",
2122
+ ""
1890
2123
  ].join("\n"))
1891
2124
  };
1892
- var insertCodeblock = (view) => {
1893
- const { selection: { main }, doc } = view.state;
1894
- const { number } = doc.lineAt(main.anchor);
1895
- const { from } = doc.line(number);
1896
- snippets.codeblock(view, null, from, from);
1897
- };
1898
2125
  var insertTable = (view) => {
1899
2126
  const { selection: { main }, doc } = view.state;
1900
2127
  const { number } = doc.lineAt(main.anchor);
1901
2128
  const { from } = doc.line(number);
1902
2129
  snippets.table(view, null, from, from);
1903
2130
  };
1904
- var toggleBold = toggleStyle("**");
1905
- var toggleItalic = toggleStyle("_");
1906
- var toggleStrikethrough = toggleStyle("~~");
1907
- var toggleList = (view) => {
2131
+ var removeLinkInner = (from, to, changes, state) => {
2132
+ syntaxTree2(state).iterate({
2133
+ from,
2134
+ to,
2135
+ enter: (node) => {
2136
+ if (node.name === "Link" && node.from < to && node.to > from) {
2137
+ node.node.cursor().iterate((node2) => {
2138
+ const { name } = node2;
2139
+ if (name === "LinkMark" || name === "LinkLabel") {
2140
+ changes.push({
2141
+ from: node2.from,
2142
+ to: node2.to
2143
+ });
2144
+ } else if (name === "LinkTitle" || name === "URL") {
2145
+ changes.push({
2146
+ from: skipSpaces(node2.from, state.doc, -1),
2147
+ to: skipSpaces(node2.to, state.doc, 1)
2148
+ });
2149
+ }
2150
+ });
2151
+ return false;
2152
+ }
2153
+ }
2154
+ });
2155
+ };
2156
+ var removeLink = ({ state, dispatch }) => {
2157
+ const changes = [];
2158
+ for (const { from, to } of state.selection.ranges) {
2159
+ removeLinkInner(from, to, changes, state);
2160
+ }
2161
+ if (!changes) {
2162
+ return false;
2163
+ }
2164
+ dispatch(state.update({
2165
+ changes,
2166
+ userEvent: "format.link.remove",
2167
+ scrollIntoView: true
2168
+ }));
2169
+ return true;
2170
+ };
2171
+ var addLink = ({ state, dispatch }) => {
2172
+ const changes = state.changeByRange((range) => {
2173
+ let { from, to } = range;
2174
+ const cutStyles = [];
2175
+ let okay = null;
2176
+ syntaxTree2(state).iterate({
2177
+ from,
2178
+ to,
2179
+ enter: (node) => {
2180
+ if (Object.hasOwn(Textblocks, node.name)) {
2181
+ okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node, state.doc);
2182
+ } else if (Object.hasOwn(InlineMarker, node.name)) {
2183
+ const sNode = node.node;
2184
+ if (node.from < from && node.to <= to) {
2185
+ if (sNode.firstChild.to === from) {
2186
+ from = node.from;
2187
+ } else {
2188
+ cutStyles.push(sNode);
2189
+ }
2190
+ } else if (node.from >= from && node.to > to) {
2191
+ if (sNode.lastChild.from === to) {
2192
+ to = node.to;
2193
+ } else {
2194
+ cutStyles.push(sNode);
2195
+ }
2196
+ }
2197
+ }
2198
+ }
2199
+ });
2200
+ if (okay === null) {
2201
+ const line = state.doc.lineAt(from);
2202
+ okay = to <= line.to && !/\S/.test(line.text.slice(from - line.from));
2203
+ }
2204
+ if (!okay) {
2205
+ return {
2206
+ range
2207
+ };
2208
+ }
2209
+ const changes2 = [];
2210
+ const changesAfter = [];
2211
+ removeLinkInner(from, to, changesAfter, state);
2212
+ let cursorOffset = 1;
2213
+ for (const style of cutStyles) {
2214
+ const type = InlineMarker[style.name];
2215
+ const mark2 = inlineMarkerText(type);
2216
+ if (style.from < from) {
2217
+ changes2.push({
2218
+ from: skipSpaces(from, state.doc, -1),
2219
+ insert: mark2
2220
+ });
2221
+ changesAfter.push({
2222
+ from: skipSpaces(from, state.doc, 1, to),
2223
+ insert: mark2
2224
+ });
2225
+ } else {
2226
+ changes2.push({
2227
+ from: skipSpaces(to, state.doc, -1, from),
2228
+ insert: mark2
2229
+ });
2230
+ const after = skipSpaces(to, state.doc, 1);
2231
+ if (after === to) {
2232
+ cursorOffset += mark2.length;
2233
+ }
2234
+ changesAfter.push({
2235
+ from: after,
2236
+ insert: mark2
2237
+ });
2238
+ }
2239
+ }
2240
+ changes2.push({
2241
+ from,
2242
+ insert: "["
2243
+ }, {
2244
+ from: to,
2245
+ insert: "]()"
2246
+ });
2247
+ const changeSet = state.changes(changes2.concat(changesAfter));
2248
+ return {
2249
+ changes: changeSet,
2250
+ range: EditorSelection.cursor(changeSet.mapPos(to, 1) - cursorOffset)
2251
+ };
2252
+ });
2253
+ if (changes.changes.empty) {
2254
+ return false;
2255
+ }
2256
+ dispatch(state.update(changes, {
2257
+ userEvent: "format.link.add",
2258
+ scrollIntoView: true
2259
+ }));
2260
+ return true;
2261
+ };
2262
+ var addList = (type) => ({ state, dispatch }) => {
2263
+ let lastBlock = -1;
2264
+ let counter = 1;
2265
+ let first = true;
2266
+ let parentColumn = null;
2267
+ const blocks = [];
2268
+ for (const { from, to } of state.selection.ranges) {
2269
+ syntaxTree2(state).iterate({
2270
+ from,
2271
+ to,
2272
+ enter: (node) => {
2273
+ if (Object.hasOwn(Textblocks, node.name) && node.name !== "TableCell" || node.name === "Table") {
2274
+ if (first) {
2275
+ let before = node.node.prevSibling;
2276
+ while (before && /Mark$/.test(before.name)) {
2277
+ before = before.prevSibling;
2278
+ }
2279
+ if (before?.name === (type === 0 ? "OrderedList" : "BulletList")) {
2280
+ const item = before.lastChild;
2281
+ const itemLine = state.doc.lineAt(item.from);
2282
+ const itemText = itemLine.text.slice(item.from - itemLine.from);
2283
+ parentColumn = item.from - itemLine.from + /^\s*/.exec(itemText)[0].length;
2284
+ if (type === 0) {
2285
+ const mark2 = /^\s*(\d+)[.)]/.exec(itemText);
2286
+ if (mark2) {
2287
+ parentColumn += mark2[1].length;
2288
+ counter = +mark2[1] + 1;
2289
+ }
2290
+ }
2291
+ }
2292
+ first = false;
2293
+ }
2294
+ if (node.from === lastBlock) {
2295
+ return;
2296
+ }
2297
+ lastBlock = node.from;
2298
+ blocks.push({
2299
+ node: node.node,
2300
+ counter,
2301
+ parentColumn
2302
+ });
2303
+ counter++;
2304
+ return false;
2305
+ }
2306
+ },
2307
+ leave: (node) => {
2308
+ if (node.name === "BulletList" || node.name === "OrderedList" || node.name === "Blockquote") {
2309
+ counter = 1;
2310
+ parentColumn = null;
2311
+ }
2312
+ }
2313
+ });
2314
+ }
2315
+ if (!blocks.length) {
2316
+ const { from, to } = state.doc.lineAt(state.selection.main.anchor);
2317
+ if (from === to) {
2318
+ dispatch(state.update({
2319
+ changes: [
2320
+ {
2321
+ from,
2322
+ insert: type === 1 ? "- " : type === 0 ? "1. " : "- [ ] "
2323
+ }
2324
+ ],
2325
+ userEvent: "format.list.add",
2326
+ scrollIntoView: true
2327
+ }));
2328
+ return true;
2329
+ }
2330
+ return false;
2331
+ }
2332
+ const changes = [];
2333
+ for (let i = 0; i < blocks.length; i++) {
2334
+ const { node, counter: counter2, parentColumn: parentColumn2 } = blocks[i];
2335
+ const nodeFrom = node.name === "CodeBlock" ? node.from - 4 : node.from;
2336
+ let padding = nodeFrom > 0 && !/\s/.test(state.doc.sliceString(nodeFrom - 1, nodeFrom)) ? 1 : 0;
2337
+ if (type === 0) {
2338
+ padding += String(counter2).length;
2339
+ }
2340
+ let line = state.doc.lineAt(nodeFrom);
2341
+ const column = nodeFrom - line.from;
2342
+ if (parentColumn2 !== null && parentColumn2 > column) {
2343
+ padding = Math.max(padding, parentColumn2 - column);
2344
+ }
2345
+ let mark2;
2346
+ if (type === 0) {
2347
+ let max = counter2;
2348
+ for (let j = i + 1; j < blocks.length; j++) {
2349
+ if (blocks[j].counter !== max + 1) {
2350
+ break;
2351
+ }
2352
+ max++;
2353
+ }
2354
+ const num = String(counter2);
2355
+ padding = Math.max(String(max).length, padding);
2356
+ mark2 = " ".repeat(Math.max(0, padding - num.length)) + num + ". ";
2357
+ } else {
2358
+ mark2 = " ".repeat(padding) + "- " + (type === 2 ? "[ ] " : "");
2359
+ }
2360
+ changes.push({
2361
+ from: nodeFrom,
2362
+ insert: mark2
2363
+ });
2364
+ while (line.to < node.to) {
2365
+ line = state.doc.lineAt(line.to + 1);
2366
+ const open = /^[\s>]*/.exec(line.text)[0].length;
2367
+ changes.push({
2368
+ from: line.from + Math.min(open, column),
2369
+ insert: " ".repeat(mark2.length)
2370
+ });
2371
+ }
2372
+ }
2373
+ if (type === 0) {
2374
+ const last = blocks[blocks.length - 1];
2375
+ let next = last.node.nextSibling;
2376
+ while (next && /Mark$/.test(next.name)) {
2377
+ next = next.nextSibling;
2378
+ }
2379
+ if (next?.name === "OrderedList") {
2380
+ renumberListItems(next.firstChild, last.counter + 1, changes, state.doc);
2381
+ }
2382
+ }
2383
+ dispatch(state.update({
2384
+ changes,
2385
+ userEvent: "format.list.add",
2386
+ scrollIntoView: true
2387
+ }));
2388
+ return true;
2389
+ };
2390
+ var removeList = (type) => ({ state, dispatch }) => {
2391
+ let lastBlock = -1;
2392
+ const changes = [];
2393
+ const stack = [];
2394
+ const targetNodeType = type === 0 ? "OrderedList" : type === 1 ? "BulletList" : "TaskList";
2395
+ for (const { from, to } of state.selection.ranges) {
2396
+ syntaxTree2(state).iterate({
2397
+ from,
2398
+ to,
2399
+ enter: (node) => {
2400
+ const { name } = node;
2401
+ if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
2402
+ stack.push(name);
2403
+ } else if (name === "Task" && stack[stack.length - 1] === "BulletList") {
2404
+ stack[stack.length - 1] = "TaskList";
2405
+ }
2406
+ },
2407
+ leave: (node) => {
2408
+ const { name } = node;
2409
+ if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
2410
+ stack.pop();
2411
+ } else if (name === "ListItem" && stack[stack.length - 1] === targetNodeType && node.from !== lastBlock) {
2412
+ lastBlock = node.from;
2413
+ let line = state.doc.lineAt(node.from);
2414
+ const mark2 = /^\s*(\d+[.)] |[-*+] (\[[ x]\] )?)/.exec(line.text.slice(node.from - line.from));
2415
+ if (!mark2) {
2416
+ return false;
2417
+ }
2418
+ const column = node.from - line.from;
2419
+ changes.push({
2420
+ from: node.from,
2421
+ to: node.from + mark2[0].length
2422
+ });
2423
+ while (line.to < node.to) {
2424
+ line = state.doc.lineAt(line.to + 1);
2425
+ const open = /^[\s>]*/.exec(line.text)[0].length;
2426
+ if (open > column) {
2427
+ changes.push({
2428
+ from: line.from + column,
2429
+ to: line.from + Math.min(column + mark2[0].length, open)
2430
+ });
2431
+ }
2432
+ }
2433
+ if (node.to >= to) {
2434
+ renumberListItems(node.node.nextSibling, 1, changes, state.doc);
2435
+ }
2436
+ return false;
2437
+ }
2438
+ }
2439
+ });
2440
+ }
2441
+ if (!changes.length) {
2442
+ return false;
2443
+ }
2444
+ dispatch(state.update({
2445
+ changes,
2446
+ userEvent: "format.list.remove",
2447
+ scrollIntoView: true
2448
+ }));
2449
+ return true;
2450
+ };
2451
+ var toggleList = (type) => (target) => {
2452
+ const formatting2 = getFormatting(target.state);
2453
+ const active = formatting2.listStyle === (type === 1 ? "bullet" : type === 0 ? "ordered" : "task");
2454
+ return (active ? removeList(type) : addList(type))(target);
2455
+ };
2456
+ var renumberListItems = (item, counter, changes, doc) => {
2457
+ for (; item; item = item.nextSibling) {
2458
+ if (item.name === "ListItem") {
2459
+ const number = /(\s*)(\d+)[.)]/.exec(doc.sliceString(item.from, item.from + 10));
2460
+ if (!number || +number[2] === counter) {
2461
+ break;
2462
+ }
2463
+ const size = number[1].length + number[2].length;
2464
+ const newNum = String(counter);
2465
+ changes.push({
2466
+ from: item.from + Math.max(0, size - newNum.length),
2467
+ to: item.from + size,
2468
+ insert: newNum
2469
+ });
2470
+ counter++;
2471
+ }
2472
+ }
2473
+ };
2474
+ var setBlockquote = (enable) => ({ state, dispatch }) => {
2475
+ const lines = [];
2476
+ let lastBlock = -1;
2477
+ for (const { from, to } of state.selection.ranges) {
2478
+ syntaxTree2(state).iterate({
2479
+ from,
2480
+ to,
2481
+ enter: (node) => {
2482
+ if (Object.hasOwn(Textblocks, node.name) || node.name === "Table") {
2483
+ if (node.from === lastBlock) {
2484
+ return false;
2485
+ }
2486
+ lastBlock = node.from;
2487
+ let line = state.doc.lineAt(node.from);
2488
+ if (line.number > 1) {
2489
+ const prevLine = state.doc.line(line.number - 1);
2490
+ if (/^[>\s]*$/.test(prevLine.text)) {
2491
+ if (!enable || lines.length && lines[lines.length - 1].number === prevLine.number - 1) {
2492
+ lines.push(prevLine);
2493
+ }
2494
+ }
2495
+ }
2496
+ for (; ; ) {
2497
+ lines.push(line);
2498
+ if (line.to >= node.to) {
2499
+ break;
2500
+ }
2501
+ line = state.doc.line(line.number + 1);
2502
+ }
2503
+ if (!enable && line.number < state.doc.lines) {
2504
+ const nextLine = state.doc.line(line.number + 1);
2505
+ if (/^[>\s]*$/.test(nextLine.text)) {
2506
+ lines.push(nextLine);
2507
+ }
2508
+ }
2509
+ return false;
2510
+ }
2511
+ }
2512
+ });
2513
+ }
2514
+ const changes = [];
2515
+ for (const line of lines) {
2516
+ if (enable) {
2517
+ changes.push({
2518
+ from: line.from,
2519
+ insert: /\S/.test(line.text) ? "> " : ">"
2520
+ });
2521
+ } else {
2522
+ const quote = /((?:[\s>\-+*]|\d+[.)])*?)> ?/.exec(line.text);
2523
+ if (quote) {
2524
+ changes.push({
2525
+ from: line.from + quote[1].length,
2526
+ to: line.from + quote[0].length
2527
+ });
2528
+ }
2529
+ }
2530
+ }
2531
+ if (!changes.length) {
2532
+ return false;
2533
+ }
2534
+ dispatch(state.update({
2535
+ changes,
2536
+ userEvent: enable ? "format.blockquote.add" : "format.blockquote.remove",
2537
+ scrollIntoView: true
2538
+ }));
2539
+ return true;
2540
+ };
2541
+ var addBlockquote = setBlockquote(true);
2542
+ var removeBlockquote = setBlockquote(false);
2543
+ var toggleBlockquote = (target) => {
2544
+ return (getFormatting(target.state).blockQuote ? removeBlockquote : addBlockquote)(target);
2545
+ };
2546
+ var addCodeblock = (target) => {
2547
+ const { state, dispatch } = target;
2548
+ const { selection } = state;
2549
+ if (selection.ranges.length === 1 && selection.main.empty) {
2550
+ const { head } = selection.main;
2551
+ const line = state.doc.lineAt(head);
2552
+ if (!/\S/.test(line.text) && head === line.from) {
2553
+ snippets.codeblock(target, null, line.from, line.to);
2554
+ return true;
2555
+ }
2556
+ }
2557
+ const ranges = [];
2558
+ for (const { from, to } of selection.ranges) {
2559
+ let blockFrom = from;
2560
+ let blockTo = to;
2561
+ syntaxTree2(state).iterate({
2562
+ from,
2563
+ to,
2564
+ enter: (node) => {
2565
+ if (Object.hasOwn(Textblocks, node.name)) {
2566
+ if (from >= node.from && to <= node.to) {
2567
+ blockFrom = node.from;
2568
+ blockTo = node.to;
2569
+ } else {
2570
+ blockFrom = Math.min(blockFrom, state.doc.lineAt(node.from).from);
2571
+ blockTo = Math.max(blockTo, state.doc.lineAt(node.to).to);
2572
+ }
2573
+ }
2574
+ }
2575
+ });
2576
+ if (ranges.length && ranges[ranges.length - 1].to >= blockFrom - 1) {
2577
+ ranges[ranges.length - 1].to = blockTo;
2578
+ } else {
2579
+ ranges.push({
2580
+ from: blockFrom,
2581
+ to: blockTo
2582
+ });
2583
+ }
2584
+ }
2585
+ if (!ranges.length) {
2586
+ return false;
2587
+ }
2588
+ const changes = ranges.map(({ from, to }) => {
2589
+ const column = from - state.doc.lineAt(from).from;
2590
+ return [
2591
+ {
2592
+ from,
2593
+ insert: "```\n" + " ".repeat(column)
2594
+ },
2595
+ {
2596
+ from: to,
2597
+ insert: "\n" + " ".repeat(column) + "```"
2598
+ }
2599
+ ];
2600
+ });
2601
+ dispatch(state.update({
2602
+ changes,
2603
+ userEvent: "format.codeblock.add",
2604
+ scrollIntoView: true
2605
+ }));
2606
+ return true;
2607
+ };
2608
+ var removeCodeblock = ({ state, dispatch }) => {
2609
+ const changes = [];
2610
+ let lastBlock = -1;
2611
+ for (const { from, to } of state.selection.ranges) {
2612
+ syntaxTree2(state).iterate({
2613
+ from,
2614
+ to,
2615
+ enter: (node) => {
2616
+ if (Textblocks[node.name] === "codeblock" && lastBlock !== node.from) {
2617
+ lastBlock = node.from;
2618
+ const firstLine = state.doc.lineAt(node.from);
2619
+ if (node.name === "FencedCode") {
2620
+ changes.push({
2621
+ from: node.from,
2622
+ to: firstLine.to + 1 + node.from - firstLine.from
2623
+ });
2624
+ const lastLine = state.doc.lineAt(node.to);
2625
+ if (/^([\s>]|[-*+] |\d+[).])*`+$/.test(lastLine.text)) {
2626
+ changes.push({
2627
+ from: lastLine.from - (lastLine.number === firstLine.number + 1 ? 0 : 1),
2628
+ to: lastLine.to
2629
+ });
2630
+ }
2631
+ } else {
2632
+ const column = node.from - firstLine.from;
2633
+ for (let line = firstLine; ; line = state.doc.line(line.number + 1)) {
2634
+ changes.push({
2635
+ from: line.from + column - 4,
2636
+ to: line.from + column
2637
+ });
2638
+ if (line.to >= node.to) {
2639
+ break;
2640
+ }
2641
+ }
2642
+ }
2643
+ }
2644
+ }
2645
+ });
2646
+ }
2647
+ if (!changes.length) {
2648
+ return false;
2649
+ }
2650
+ dispatch(state.update({
2651
+ changes,
2652
+ userEvent: "format.codeblock.remove",
2653
+ scrollIntoView: true
2654
+ }));
2655
+ return true;
2656
+ };
2657
+ var toggleCodeblock = (target) => {
2658
+ return (getFormatting(target.state).blockType === "codeblock" ? removeCodeblock : addCodeblock)(target);
1908
2659
  };
1909
2660
  var formatting = (options = {}) => {
1910
2661
  return [
1911
2662
  keymap5.of([
1912
2663
  {
1913
2664
  key: "meta-b",
1914
- run: toggleBold
2665
+ run: toggleStrong
1915
2666
  }
1916
2667
  ]),
1917
2668
  styling()
@@ -1965,6 +2716,209 @@ var styling = () => {
1965
2716
  })
1966
2717
  ];
1967
2718
  };
2719
+ var InlineMarker = {
2720
+ Emphasis: 1,
2721
+ StrongEmphasis: 0,
2722
+ InlineCode: 3,
2723
+ Strikethrough: 2
2724
+ };
2725
+ var IgnoreInline = /* @__PURE__ */ new Set([
2726
+ "Autolink",
2727
+ "CodeMark",
2728
+ "CodeText",
2729
+ "Comment",
2730
+ "EmphasisMark",
2731
+ "Hardbreak",
2732
+ "HeaderMark",
2733
+ "HTMLTag",
2734
+ "LinkMark",
2735
+ "ListMark",
2736
+ "ProcessingInstruction",
2737
+ "QuoteMark",
2738
+ "StrikethroughMark",
2739
+ "SubscriptMark",
2740
+ "SuperscriptMark",
2741
+ "TaskMarker"
2742
+ ]);
2743
+ var Textblocks = {
2744
+ ATXHeading1: "heading1",
2745
+ ATXHeading2: "heading2",
2746
+ ATXHeading3: "heading3",
2747
+ ATXHeading4: "heading4",
2748
+ ATXHeading5: "heading5",
2749
+ ATXHeading6: "heading6",
2750
+ CodeBlock: "codeblock",
2751
+ FencedCode: "codeblock",
2752
+ Paragraph: "paragraph",
2753
+ SetextHeading1: "heading1",
2754
+ SetextHeading2: "heading2",
2755
+ TableCell: "tablecell",
2756
+ Task: "paragraph"
2757
+ };
2758
+ var getFormatting = (state) => {
2759
+ let blockType = null;
2760
+ const inline = [
2761
+ null,
2762
+ null,
2763
+ null,
2764
+ null
2765
+ ];
2766
+ let link2 = false;
2767
+ let blockQuote = null;
2768
+ let listStyle = null;
2769
+ const stack = [];
2770
+ let currentBlock = null;
2771
+ const advanceInline = (upto) => {
2772
+ if (!currentBlock) {
2773
+ return;
2774
+ }
2775
+ upto = Math.min(upto, currentBlock.end);
2776
+ if (upto <= currentBlock.pos) {
2777
+ return;
2778
+ }
2779
+ for (let i = 0; i < currentBlock.active.length; i++) {
2780
+ if (inline[i] === false) {
2781
+ continue;
2782
+ } else if (currentBlock.active[i]) {
2783
+ inline[i] = true;
2784
+ } else if (/\S/.test(state.doc.sliceString(currentBlock.pos, upto))) {
2785
+ inline[i] = false;
2786
+ }
2787
+ }
2788
+ currentBlock.pos = upto;
2789
+ };
2790
+ const skipInline = (upto) => {
2791
+ if (currentBlock && upto > currentBlock.pos) {
2792
+ currentBlock.pos = Math.min(upto, currentBlock.end);
2793
+ }
2794
+ };
2795
+ const { selection } = state;
2796
+ for (const range of selection.ranges) {
2797
+ if (range.empty && inline.some((v) => v === null)) {
2798
+ const contextSize = Math.min(range.head, 6);
2799
+ const contextBefore = state.doc.sliceString(range.head - contextSize, range.head);
2800
+ let contextAfter = state.doc.sliceString(range.head, range.head + contextSize);
2801
+ for (let i = 0; i < contextSize; i++) {
2802
+ const ch = contextAfter[i];
2803
+ if (ch !== contextBefore[contextBefore.length - 1 - i] || !/[~`*]/.test(ch)) {
2804
+ contextAfter = contextAfter.slice(0, i);
2805
+ break;
2806
+ }
2807
+ }
2808
+ for (let i = 0; i < inline.length; i++) {
2809
+ const mark2 = inlineMarkerText(i);
2810
+ const found = contextAfter.indexOf(mark2);
2811
+ if (found > -1) {
2812
+ contextAfter = contextAfter.slice(0, found) + contextAfter.slice(found + mark2.length);
2813
+ if (inline[i] === null) {
2814
+ inline[i] = true;
2815
+ }
2816
+ }
2817
+ }
2818
+ }
2819
+ syntaxTree2(state).iterate({
2820
+ from: range.from,
2821
+ to: range.to,
2822
+ enter: (node) => {
2823
+ advanceInline(node.from);
2824
+ const { name } = node;
2825
+ if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
2826
+ stack.push(name);
2827
+ } else if (name === "Link") {
2828
+ link2 = true;
2829
+ } else if (Object.hasOwn(Textblocks, name) && (range.empty || node.to > range.from || node.from < range.to)) {
2830
+ if (name === "Task" && stack[stack.length - 1] === "BulletList") {
2831
+ stack[stack.length - 1] = "TaskList";
2832
+ }
2833
+ const blockCode = Textblocks[name];
2834
+ if (blockType === null) {
2835
+ blockType = blockCode;
2836
+ } else if (blockType !== blockCode) {
2837
+ blockType = false;
2838
+ }
2839
+ if (blockCode !== "codeblock" && inline.some((i) => i !== false)) {
2840
+ currentBlock = {
2841
+ pos: Math.max(range.from, node.from),
2842
+ end: Math.min(range.to, node.to),
2843
+ active: [
2844
+ false,
2845
+ false,
2846
+ false,
2847
+ false
2848
+ ]
2849
+ };
2850
+ }
2851
+ } else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
2852
+ const index = InlineMarker[name];
2853
+ if (range.empty && inline[index] === null) {
2854
+ inline[index] = true;
2855
+ }
2856
+ currentBlock.active[index] = true;
2857
+ } else if (IgnoreInline.has(name)) {
2858
+ skipInline(node.to);
2859
+ }
2860
+ },
2861
+ leave: (node) => {
2862
+ advanceInline(node.to);
2863
+ const { name } = node;
2864
+ if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
2865
+ stack.pop();
2866
+ } else if (Object.hasOwn(Textblocks, name)) {
2867
+ let hasList = false;
2868
+ let hasQuote = false;
2869
+ for (let i = stack.length - 1; i >= 0; i--) {
2870
+ if (stack[i] === "Blockquote") {
2871
+ hasQuote = true;
2872
+ } else if (!hasList) {
2873
+ hasList = stack[i] === "TaskList" ? "task" : stack[i] === "BulletList" ? "bullet" : "ordered";
2874
+ }
2875
+ }
2876
+ if (blockQuote === null) {
2877
+ blockQuote = hasQuote;
2878
+ } else if (!hasQuote && blockQuote) {
2879
+ blockQuote = false;
2880
+ }
2881
+ if (listStyle === null) {
2882
+ listStyle = hasList;
2883
+ } else if (listStyle !== hasList) {
2884
+ listStyle = false;
2885
+ }
2886
+ currentBlock = null;
2887
+ } else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
2888
+ currentBlock.active[InlineMarker[name]] = false;
2889
+ }
2890
+ }
2891
+ });
2892
+ }
2893
+ const { from, to } = state.doc.lineAt(selection.main.anchor);
2894
+ const blankLine = from === to;
2895
+ return {
2896
+ blankLine,
2897
+ blockType: blockType || null,
2898
+ blockQuote: blockQuote ?? false,
2899
+ code: inline[3] ?? false,
2900
+ emphasis: inline[1] ?? false,
2901
+ strong: inline[0] ?? false,
2902
+ strikethrough: inline[2] ?? false,
2903
+ link: link2,
2904
+ listStyle: listStyle || null
2905
+ };
2906
+ };
2907
+ var useFormattingState = () => {
2908
+ const [state, setState] = useState(null);
2909
+ const observer = useMemo(() => EditorView9.updateListener.of((update2) => {
2910
+ if (update2.docChanged || update2.selectionSet) {
2911
+ const newState = getFormatting(update2.state);
2912
+ if (!state || !compareFormatting(state, newState)) {
2913
+ setState(newState);
2914
+ }
2915
+ }
2916
+ }), []);
2917
+ return [
2918
+ state,
2919
+ observer
2920
+ ];
2921
+ };
1968
2922
 
1969
2923
  // packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
1970
2924
  import { syntaxTree as syntaxTree3 } from "@codemirror/language";
@@ -2017,8 +2971,8 @@ var heading2 = () => {
2017
2971
  // packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
2018
2972
  import { syntaxTree as syntaxTree4 } from "@codemirror/language";
2019
2973
  import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
2020
- import { Decoration as Decoration6, EditorView as EditorView9, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
2021
- var styles4 = EditorView9.baseTheme({
2974
+ import { Decoration as Decoration6, EditorView as EditorView10, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
2975
+ var styles4 = EditorView10.baseTheme({
2022
2976
  "& .cm-hr": {
2023
2977
  // Note that block-level decorations should not have vertical margins,
2024
2978
  borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
@@ -2072,7 +3026,7 @@ var hr = () => {
2072
3026
  // packages/ui/react-ui-editor/src/extensions/markdown/image.ts
2073
3027
  import { syntaxTree as syntaxTree5 } from "@codemirror/language";
2074
3028
  import { StateField as StateField3 } from "@codemirror/state";
2075
- import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType4 } from "@codemirror/view";
3029
+ import { Decoration as Decoration7, EditorView as EditorView11, WidgetType as WidgetType4 } from "@codemirror/view";
2076
3030
  var image = (options = {}) => {
2077
3031
  return StateField3.define({
2078
3032
  create: (state) => {
@@ -2099,7 +3053,7 @@ var image = (options = {}) => {
2099
3053
  add: buildDecorations4(from, to, tr.state)
2100
3054
  });
2101
3055
  },
2102
- provide: (field) => EditorView10.decorations.from(field)
3056
+ provide: (field) => EditorView11.decorations.from(field)
2103
3057
  });
2104
3058
  };
2105
3059
  var buildDecorations4 = (from, to, state) => {
@@ -2281,12 +3235,12 @@ var buildDecorations5 = (view, options) => {
2281
3235
  // packages/ui/react-ui-editor/src/extensions/markdown/table.ts
2282
3236
  import { syntaxTree as syntaxTree7 } from "@codemirror/language";
2283
3237
  import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField4 } from "@codemirror/state";
2284
- import { Decoration as Decoration9, EditorView as EditorView11, WidgetType as WidgetType6 } from "@codemirror/view";
3238
+ import { Decoration as Decoration9, EditorView as EditorView12, WidgetType as WidgetType6 } from "@codemirror/view";
2285
3239
  var table = (options = {}) => {
2286
3240
  return StateField4.define({
2287
3241
  create: (state) => update(state, options),
2288
3242
  update: (_, tr) => update(tr.state, options),
2289
- provide: (field) => EditorView11.decorations.from(field)
3243
+ provide: (field) => EditorView12.decorations.from(field)
2290
3244
  });
2291
3245
  };
2292
3246
  var update = (state, options) => {
@@ -2379,8 +3333,8 @@ var TableWidget = class extends WidgetType6 {
2379
3333
  // packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
2380
3334
  import { syntaxTree as syntaxTree8 } from "@codemirror/language";
2381
3335
  import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
2382
- import { EditorView as EditorView12, Decoration as Decoration10, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
2383
- var styles5 = EditorView12.baseTheme({
3336
+ import { EditorView as EditorView13, Decoration as Decoration10, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
3337
+ var styles5 = EditorView13.baseTheme({
2384
3338
  "& .cm-task": {
2385
3339
  color: getToken("extend.colors.blue.500")
2386
3340
  },
@@ -2813,7 +3767,7 @@ var EditorModes = [
2813
3767
  var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
2814
3768
  const { themeMode } = useThemeContext();
2815
3769
  const rootRef = useRef(null);
2816
- const [view, setView] = useState(null);
3770
+ const [view, setView] = useState2(null);
2817
3771
  useImperativeHandle(forwardedRef, () => view, [
2818
3772
  view
2819
3773
  ]);
@@ -2842,7 +3796,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
2842
3796
  selection,
2843
3797
  extensions: [
2844
3798
  // TODO(burdon): Doesn't catch errors in keymap functions.
2845
- EditorView13.exceptionSink.of((err) => {
3799
+ EditorView14.exceptionSink.of((err) => {
2846
3800
  log2.catch(err, void 0, {
2847
3801
  F: __dxlog_file3,
2848
3802
  L: 134,
@@ -2852,17 +3806,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
2852
3806
  }),
2853
3807
  // Theme.
2854
3808
  // TODO(burdon): Make configurable.
2855
- EditorView13.baseTheme(defaultTheme),
2856
- EditorView13.theme(theme ?? {}),
2857
- EditorView13.darkTheme.of(themeMode === "dark"),
2858
- EditorView13.editorAttributes.of({
3809
+ EditorView14.baseTheme(defaultTheme),
3810
+ EditorView14.theme(theme ?? {}),
3811
+ EditorView14.darkTheme.of(themeMode === "dark"),
3812
+ EditorView14.editorAttributes.of({
2859
3813
  class: slots.editor?.className ?? ""
2860
3814
  }),
2861
- EditorView13.contentAttributes.of({
3815
+ EditorView14.contentAttributes.of({
2862
3816
  class: slots.content?.className ?? ""
2863
3817
  }),
2864
3818
  // State.
2865
- EditorView13.editable.of(!readonly),
3819
+ EditorView14.editable.of(!readonly),
2866
3820
  EditorState2.readOnly.of(!!readonly),
2867
3821
  // Storage and replication.
2868
3822
  // NOTE: This must come before user extensions.
@@ -2873,7 +3827,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
2873
3827
  ...extensions
2874
3828
  ].filter(isNotFalsy3)
2875
3829
  });
2876
- const newView = new EditorView13({
3830
+ const newView = new EditorView14({
2877
3831
  state,
2878
3832
  parent: rootRef.current,
2879
3833
  scrollTo,
@@ -2980,35 +3934,49 @@ var defaultMarkdownSlots = {
2980
3934
  };
2981
3935
 
2982
3936
  // packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
2983
- import { At, CaretRight, ChatText, Code, Image, Link, ListBullets, ListChecks, ListNumbers, TextStrikethrough, Table as Table2, TextB, TextItalic } from "@phosphor-icons/react";
3937
+ import { CaretRight, ChatText, Code, CodeBlock, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic } from "@phosphor-icons/react";
2984
3938
  import { createContext } from "@radix-ui/react-context";
2985
3939
  import React2 from "react";
2986
3940
  import { Button, DensityProvider, Select } from "@dxos/react-ui";
2987
- import { getSize } from "@dxos/react-ui-theme";
3941
+ import { getSize, mx as mx4 } from "@dxos/react-ui-theme";
3942
+ var HeadingIcons = {
3943
+ "0": Paragraph,
3944
+ "1": TextHOne,
3945
+ "2": TextHTwo,
3946
+ "3": TextHThree,
3947
+ "4": TextHFour,
3948
+ "5": TextHFive,
3949
+ "6": TextHSix
3950
+ };
2988
3951
  var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
2989
- var ToolbarRoot = ({ children, onAction }) => {
3952
+ var ToolbarRoot = ({ children, onAction, state }) => {
2990
3953
  return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
2991
- onAction
3954
+ onAction,
3955
+ state
2992
3956
  }, /* @__PURE__ */ React2.createElement(DensityProvider, {
2993
3957
  density: "fine"
2994
3958
  }, /* @__PURE__ */ React2.createElement("div", {
2995
3959
  role: "toolbar",
2996
- className: "flex w-full shrink-0 p-2 gap-4 items-center whitespace-nowrap overflow-hidden"
3960
+ className: "flex w-full shrink-0 p-1 gap-4 items-center whitespace-nowrap overflow-hidden"
2997
3961
  }, children)));
2998
3962
  };
2999
- var ToolbarButton = ({ Icon, onClick, title }) => {
3000
- const { onAction } = useToolbarContext("ToolbarButton");
3001
- const handleClick = () => {
3002
- const action = onClick();
3963
+ var ToolbarButton = ({ Icon, onClick, title, getState, disable }) => {
3964
+ const { onAction, state } = useToolbarContext("ToolbarButton");
3965
+ const active = getState && state ? getState(state) : false;
3966
+ const disabled = disable && state ? disable(state) : false;
3967
+ const handleClick = (event) => {
3968
+ const action = onClick(state);
3003
3969
  if (action) {
3004
3970
  onAction?.(action);
3971
+ event.preventDefault();
3005
3972
  }
3006
3973
  };
3007
3974
  return /* @__PURE__ */ React2.createElement(Button, {
3008
3975
  variant: "ghost",
3009
- classNames: "p-2",
3010
- onClick: handleClick,
3011
- title
3976
+ classNames: mx4("p-2", active && "ring-[1px]"),
3977
+ onMouseDown: handleClick,
3978
+ title,
3979
+ disabled
3012
3980
  }, /* @__PURE__ */ React2.createElement(Icon, {
3013
3981
  className: getSize(5)
3014
3982
  }));
@@ -3017,16 +3985,21 @@ var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
3017
3985
  className: "grow"
3018
3986
  });
3019
3987
  var MarkdownHeading = () => {
3020
- const { onAction } = useToolbarContext("MarkdownFormatting");
3988
+ const { onAction, state } = useToolbarContext("MarkdownFormatting");
3989
+ const blockType = state ? state.blockType : "paragraph";
3990
+ const header = blockType && /heading(\d)/.exec(blockType);
3991
+ const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
3992
+ const HeadingIcon = HeadingIcons[value ?? "0"];
3021
3993
  return /* @__PURE__ */ React2.createElement(Select.Root, {
3022
- defaultValue: "0",
3023
- onValueChange: (value) => onAction?.({
3994
+ disabled: value === null,
3995
+ value: value ?? "0",
3996
+ onValueChange: (value2) => onAction?.({
3024
3997
  type: "heading",
3025
- data: parseInt(value)
3998
+ data: parseInt(value2)
3026
3999
  })
3027
- }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
3028
- classNames: "w-[8rem]"
3029
- }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
4000
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, null, /* @__PURE__ */ React2.createElement(HeadingIcon, {
4001
+ className: getSize(5)
4002
+ })), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
3030
4003
  value: "0"
3031
4004
  }, "Paragraph"), [
3032
4005
  1,
@@ -3044,21 +4017,39 @@ var MarkdownStyles = () => /* @__PURE__ */ React2.createElement("div", {
3044
4017
  role: "none"
3045
4018
  }, /* @__PURE__ */ React2.createElement(ToolbarButton, {
3046
4019
  Icon: TextB,
3047
- title: "Bold",
3048
- onClick: () => ({
3049
- type: "bold"
4020
+ title: "String",
4021
+ disable: (s) => s.blockType === "codeblock",
4022
+ getState: (s) => s.strong,
4023
+ onClick: (s) => ({
4024
+ type: "strong",
4025
+ data: s ? !s.strong : null
3050
4026
  })
3051
4027
  }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
3052
4028
  Icon: TextItalic,
3053
- title: "Italic",
3054
- onClick: () => ({
3055
- type: "italic"
4029
+ title: "Emphasis",
4030
+ disable: (s) => s.blockType === "codeblock",
4031
+ getState: (s) => s.emphasis,
4032
+ onClick: (s) => ({
4033
+ type: "emphasis",
4034
+ data: s ? !s.emphasis : null
3056
4035
  })
3057
4036
  }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
3058
4037
  Icon: TextStrikethrough,
3059
4038
  title: "Strike-through",
3060
- onClick: () => ({
3061
- type: "strikethrough"
4039
+ disable: (s) => s.blockType === "codeblock",
4040
+ getState: (s) => s.strikethrough,
4041
+ onClick: (s) => ({
4042
+ type: "strikethrough",
4043
+ data: s ? !s.strikethrough : null
4044
+ })
4045
+ }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
4046
+ Icon: Code,
4047
+ title: "Inline code",
4048
+ disable: (s) => s.blockType === "codeblock",
4049
+ getState: (s) => s.code,
4050
+ onClick: (s) => ({
4051
+ type: "code",
4052
+ data: s ? !s.code : null
3062
4053
  })
3063
4054
  }));
3064
4055
  var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
@@ -3066,39 +4057,51 @@ var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
3066
4057
  }, /* @__PURE__ */ React2.createElement(ToolbarButton, {
3067
4058
  Icon: ListBullets,
3068
4059
  title: "Bullet list",
3069
- onClick: () => ({
3070
- type: "list"
4060
+ getState: (s) => s.listStyle === "bullet",
4061
+ onClick: (s) => ({
4062
+ type: "list-bullet",
4063
+ data: s ? s.listStyle !== "bullet" : null
3071
4064
  })
3072
4065
  }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
3073
4066
  Icon: ListNumbers,
3074
4067
  title: "Numbered list",
3075
- onClick: () => ({
3076
- type: "list-ordered"
4068
+ getState: (s) => s.listStyle === "ordered",
4069
+ onClick: (s) => ({
4070
+ type: "list-ordered",
4071
+ data: s ? s.listStyle !== "ordered" : null
3077
4072
  })
3078
4073
  }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
3079
4074
  Icon: ListChecks,
3080
4075
  title: "Task list",
3081
- onClick: () => ({
3082
- type: "list-tasks"
4076
+ getState: (s) => s.listStyle === "task",
4077
+ onClick: (s) => ({
4078
+ type: "list-tasks",
4079
+ data: s ? s.listStyle !== "task" : null
3083
4080
  })
3084
4081
  }));
3085
4082
  var MarkdownBlocks = () => /* @__PURE__ */ React2.createElement("div", {
3086
4083
  role: "none"
3087
4084
  }, /* @__PURE__ */ React2.createElement(ToolbarButton, {
3088
4085
  Icon: CaretRight,
3089
- title: "Block quite",
3090
- onClick: () => ({
3091
- type: "blockquote"
4086
+ title: "Block quote",
4087
+ getState: (s) => s.blockQuote,
4088
+ onClick: (s) => ({
4089
+ type: "blockquote",
4090
+ data: s ? !s.blockQuote : null
3092
4091
  })
3093
4092
  }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
3094
- Icon: Code,
4093
+ Icon: CodeBlock,
3095
4094
  title: "Code block",
3096
- onClick: () => ({
3097
- type: "codeblock"
4095
+ disable: (s) => !s.blankLine,
4096
+ getState: (s) => s.blockType === "codeblock",
4097
+ onClick: (s) => ({
4098
+ type: "codeblock",
4099
+ data: s ? s.blockType !== "codeblock" : null
3098
4100
  })
3099
4101
  }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
3100
4102
  Icon: Table2,
3101
4103
  title: "Table",
4104
+ disable: (s) => !s.blankLine,
3102
4105
  onClick: () => ({
3103
4106
  type: "table"
3104
4107
  })
@@ -3108,20 +4111,10 @@ var MarkdownLinks = () => /* @__PURE__ */ React2.createElement("div", {
3108
4111
  }, /* @__PURE__ */ React2.createElement(ToolbarButton, {
3109
4112
  Icon: Link,
3110
4113
  title: "Link",
3111
- onClick: () => ({
3112
- type: "link"
3113
- })
3114
- }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
3115
- Icon: At,
3116
- title: "Mention",
3117
- onClick: () => ({
3118
- type: "mention"
3119
- })
3120
- }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
3121
- Icon: Image,
3122
- title: "Image",
3123
- onClick: () => ({
3124
- type: "image"
4114
+ getState: (s) => s.link,
4115
+ onClick: (s) => ({
4116
+ type: "link",
4117
+ data: s ? !s.link : null
3125
4118
  })
3126
4119
  }));
3127
4120
  var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null), /* @__PURE__ */ React2.createElement(MarkdownLinks, null));
@@ -3257,45 +4250,52 @@ var useActionHandler = (view) => {
3257
4250
  if (!view) {
3258
4251
  return;
3259
4252
  }
4253
+ let inlineType, listType;
3260
4254
  switch (action.type) {
3261
4255
  case "heading":
3262
4256
  setHeading(parseInt(action.data))(view);
3263
4257
  break;
3264
- case "bold":
3265
- toggleBold(view);
3266
- break;
3267
- case "italic":
3268
- toggleItalic(view);
3269
- break;
4258
+ case "strong":
4259
+ case "emphasis":
3270
4260
  case "strikethrough":
3271
- toggleStrikethrough(view);
4261
+ case "code":
4262
+ inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
4263
+ (typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
3272
4264
  break;
3273
- case "list":
3274
- toggleList(view);
4265
+ case "list-ordered":
4266
+ case "list-bullet":
4267
+ case "list-tasks":
4268
+ listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
4269
+ (action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
4270
+ break;
4271
+ case "blockquote":
4272
+ (action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
3275
4273
  break;
3276
4274
  case "codeblock":
3277
- insertCodeblock(view);
4275
+ (action.data === false ? removeCodeblock : addCodeblock)(view);
3278
4276
  break;
3279
4277
  case "table":
3280
4278
  insertTable(view);
3281
4279
  break;
4280
+ case "link":
4281
+ (action.data === false ? removeLink : addLink)(view);
4282
+ break;
3282
4283
  case "comment":
3283
4284
  createComment(view);
3284
4285
  break;
3285
4286
  }
3286
4287
  setTimeout(() => {
3287
- view.focus();
3288
- view.dispatch({
3289
- selection: view.state.selection
3290
- });
4288
+ if (!view.hasFocus) {
4289
+ view.focus();
4290
+ }
3291
4291
  });
3292
4292
  };
3293
4293
  };
3294
4294
 
3295
4295
  // packages/ui/react-ui-editor/src/hooks/useEditorView.ts
3296
- import { useState as useState2 } from "react";
4296
+ import { useState as useState3 } from "react";
3297
4297
  var useEditorView = () => {
3298
- const [view, setView] = useState2(null);
4298
+ const [view, setView] = useState3(null);
3299
4299
  return [
3300
4300
  (ref) => {
3301
4301
  setView(ref);
@@ -3305,15 +4305,15 @@ var useEditorView = () => {
3305
4305
  };
3306
4306
 
3307
4307
  // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
3308
- import { EditorSelection, EditorState as EditorState3 } from "@codemirror/state";
3309
- import { EditorView as EditorView14 } from "@codemirror/view";
3310
- import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
4308
+ import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
4309
+ import { EditorView as EditorView15 } from "@codemirror/view";
4310
+ import { useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
3311
4311
  import { log as log4 } from "@dxos/log";
3312
4312
  import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
3313
4313
  var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
3314
4314
  var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}) => {
3315
4315
  const onUpdate = useRef2();
3316
- const [view, setView] = useState3();
4316
+ const [view, setView] = useState4();
3317
4317
  const parentRef = useRef2(null);
3318
4318
  useEffect3(() => {
3319
4319
  if (parentRef.current) {
@@ -3322,7 +4322,7 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
3322
4322
  selection,
3323
4323
  extensions: [
3324
4324
  // TODO(burdon): Doesn't catch errors in keymap functions.
3325
- EditorView14.exceptionSink.of((err) => {
4325
+ EditorView15.exceptionSink.of((err) => {
3326
4326
  log4.catch(err, void 0, {
3327
4327
  F: __dxlog_file5,
3328
4328
  L: 57,
@@ -3331,12 +4331,12 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
3331
4331
  });
3332
4332
  }),
3333
4333
  extensions,
3334
- EditorView14.updateListener.of(() => {
4334
+ EditorView15.updateListener.of(() => {
3335
4335
  onUpdate.current?.();
3336
4336
  })
3337
4337
  ].filter(isNotFalsy4)
3338
4338
  });
3339
- const view2 = new EditorView14({
4339
+ const view2 = new EditorView15({
3340
4340
  parent: parentRef.current,
3341
4341
  scrollTo,
3342
4342
  state,
@@ -3360,7 +4360,7 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
3360
4360
  useEffect3(() => {
3361
4361
  if (view) {
3362
4362
  if (!selection && !view.state.selection.main.anchor) {
3363
- selection = EditorSelection.single(view.state.doc.line(1).to);
4363
+ selection = EditorSelection2.single(view.state.doc.line(1).to);
3364
4364
  }
3365
4365
  if (selection || scrollTo) {
3366
4366
  onUpdate.current = () => {
@@ -3393,19 +4393,19 @@ var createDataExtensions = ({ readonly = false } = {}) => {
3393
4393
  return [
3394
4394
  //
3395
4395
  EditorState3.readOnly.of(readonly),
3396
- EditorView14.editable.of(!readonly)
4396
+ EditorView15.editable.of(!readonly)
3397
4397
  ];
3398
4398
  };
3399
4399
  var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
3400
4400
  return [
3401
4401
  //
3402
- EditorView14.baseTheme(defaultTheme),
3403
- theme && EditorView14.theme(theme),
3404
- EditorView14.darkTheme.of(themeMode === "dark"),
3405
- EditorView14.editorAttributes.of({
4402
+ EditorView15.baseTheme(defaultTheme),
4403
+ theme && EditorView15.theme(theme),
4404
+ EditorView15.darkTheme.of(themeMode === "dark"),
4405
+ EditorView15.editorAttributes.of({
3406
4406
  class: slots?.editor?.className ?? ""
3407
4407
  }),
3408
- EditorView14.contentAttributes.of({
4408
+ EditorView15.contentAttributes.of({
3409
4409
  class: slots?.content?.className ?? ""
3410
4410
  })
3411
4411
  ].filter(isNotFalsy4);
@@ -3413,7 +4413,7 @@ var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
3413
4413
 
3414
4414
  // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
3415
4415
  import get4 from "lodash.get";
3416
- import { useEffect as useEffect4, useState as useState4 } from "react";
4416
+ import { useEffect as useEffect4, useState as useState5 } from "react";
3417
4417
  import { generateName } from "@dxos/display-name";
3418
4418
  import { getRawDoc } from "@dxos/echo-schema";
3419
4419
  import { invariant as invariant3 } from "@dxos/invariant";
@@ -3421,7 +4421,7 @@ import { isAutomergeObject } from "@dxos/react-client/echo";
3421
4421
  var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
3422
4422
  var useTextModel = (props) => {
3423
4423
  const { identity, space, text } = props;
3424
- const [model, setModel] = useState4();
4424
+ const [model, setModel] = useState5();
3425
4425
  useEffect4(() => setModel(createModel(props)), [
3426
4426
  identity,
3427
4427
  space,
@@ -3430,7 +4430,7 @@ var useTextModel = (props) => {
3430
4430
  return model;
3431
4431
  };
3432
4432
  var useInMemoryTextModel = ({ id, defaultContent }) => {
3433
- const [content, setContent] = useState4(defaultContent ?? "");
4433
+ const [content, setContent] = useState5(defaultContent ?? "");
3434
4434
  return {
3435
4435
  id,
3436
4436
  content,
@@ -3490,6 +4490,8 @@ export {
3490
4490
  Cursor,
3491
4491
  Doc,
3492
4492
  EditorModes,
4493
+ Inline,
4494
+ List,
3493
4495
  MarkdownEditor,
3494
4496
  RemoteSelectionsDecorator,
3495
4497
  SpaceAwarenessProvider,
@@ -3498,6 +4500,11 @@ export {
3498
4500
  Toolbar,
3499
4501
  YText,
3500
4502
  YXmlFragment,
4503
+ addBlockquote,
4504
+ addCodeblock,
4505
+ addLink,
4506
+ addList,
4507
+ addStyle,
3501
4508
  autocomplete,
3502
4509
  automerge,
3503
4510
  awareness,
@@ -3507,6 +4514,7 @@ export {
3507
4514
  code2 as code,
3508
4515
  codeTheme,
3509
4516
  comments,
4517
+ compareFormatting,
3510
4518
  createBasicBundle,
3511
4519
  createComment,
3512
4520
  createDataExtensions,
@@ -3519,11 +4527,11 @@ export {
3519
4527
  defaultTheme,
3520
4528
  focusComment,
3521
4529
  formatting,
4530
+ getFormatting,
3522
4531
  getToken,
3523
4532
  heading2 as heading,
3524
4533
  hr,
3525
4534
  image,
3526
- insertCodeblock,
3527
4535
  insertTable,
3528
4536
  keymap7 as keymap,
3529
4537
  link,
@@ -3536,22 +4544,33 @@ export {
3536
4544
  mention,
3537
4545
  modelState,
3538
4546
  outliner,
4547
+ removeBlockquote,
4548
+ removeCodeblock,
4549
+ removeLink,
4550
+ removeList,
4551
+ removeStyle,
4552
+ setBlockquote,
3539
4553
  setComments,
3540
4554
  setHeading,
3541
4555
  setSelection,
4556
+ setStyle,
3542
4557
  table,
3543
4558
  tags2 as tags,
3544
4559
  tasklist,
3545
4560
  textTheme,
3546
- toggleBold,
3547
- toggleItalic,
4561
+ toggleBlockquote,
4562
+ toggleCodeblock,
4563
+ toggleEmphasis,
4564
+ toggleInlineCode,
3548
4565
  toggleList,
3549
4566
  toggleStrikethrough,
4567
+ toggleStrong,
3550
4568
  toggleStyle,
3551
4569
  typewriter,
3552
4570
  useActionHandler,
3553
4571
  useComments,
3554
4572
  useEditorView,
4573
+ useFormattingState,
3555
4574
  useInMemoryTextModel,
3556
4575
  useTextEditor,
3557
4576
  useTextModel,