@dxos/react-ui-editor 0.4.5-main.b8bc204 → 0.4.5-main.c8d4ae3

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.
@@ -8,7 +8,7 @@ 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 EditorView15 } from "@codemirror/view";
11
+ import { EditorView as EditorView16 } from "@codemirror/view";
12
12
  import { useFocusableGroup } from "@fluentui/react-tabster";
13
13
  import defaultsDeep2 from "lodash.defaultsdeep";
14
14
  import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2, useMemo as useMemo2 } from "react";
@@ -102,8 +102,8 @@ var annotations = (options = {}) => {
102
102
  annotationsState
103
103
  ], (state) => {
104
104
  const annotations2 = state.field(annotationsState);
105
- const decorations = annotations2.map((annotation) => {
106
- const range = Cursor.getRangeFromCursor(state, annotation.cursor);
105
+ const decorations = annotations2.map((annotation2) => {
106
+ const range = Cursor.getRangeFromCursor(state, annotation2.cursor);
107
107
  return range && annotationMark.range(range.from, range.to);
108
108
  }).filter(isNotFalsy);
109
109
  return Decoration.set(decorations);
@@ -1116,8 +1116,8 @@ var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue)
1116
1116
 
1117
1117
  // packages/ui/react-ui-editor/src/styles/layout.ts
1118
1118
  var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
1119
- var editorFillLayoutRoot = "min-bs-full grid";
1120
- var editorFillLayoutEditor = "min-bs-full";
1119
+ var editorFillLayoutRoot = "bs-full overflow-hidden grid";
1120
+ var editorFillLayoutEditor = "bs-full overflow-hidden [&>.cm-scroller]:bs-full [&>.cm-scroller]:overflow-y-auto";
1121
1121
  var editorHalfViewportOverscrollContent = "after:block after:min-bs-[50dvh] after:pointer-events-none";
1122
1122
 
1123
1123
  // packages/ui/react-ui-editor/src/util.ts
@@ -1553,15 +1553,66 @@ var useComments = (view, id, comments2 = []) => {
1553
1553
  ]);
1554
1554
  };
1555
1555
 
1556
- // packages/ui/react-ui-editor/src/extensions/listener.ts
1556
+ // packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts
1557
+ import { Facet as Facet4, Transaction } from "@codemirror/state";
1557
1558
  import { EditorView as EditorView7 } from "@codemirror/view";
1559
+ var cursorLineMarginFacet = Facet4.define({
1560
+ combine: (input) => input[0] ?? 3
1561
+ });
1562
+ var annotation = "cursorLineMargin";
1563
+ var lineAtPos = (s, pos) => s.doc.lineAt(pos).number;
1564
+ var cursorLineMargin = EditorView7.updateListener.of(({ transactions, state, selectionSet, startState, view }) => {
1565
+ if (transactions.length < 1 || transactions.some((tr) => tr.isUserEvent(annotation))) {
1566
+ return;
1567
+ }
1568
+ const s = state;
1569
+ const { main } = s.selection;
1570
+ const cursorLineMargin2 = s.facet(cursorLineMarginFacet);
1571
+ const rect = view.dom.getBoundingClientRect();
1572
+ const viewportTop = rect.top - view.documentTop;
1573
+ const viewportBottom = rect.bottom - view.documentTop;
1574
+ const mainLine = lineAtPos(s, main.head);
1575
+ const _visTopLine = lineAtPos(s, view.lineBlockAtHeight(viewportTop).from);
1576
+ const botLineBlk = view.lineBlockAtHeight(viewportBottom);
1577
+ const visBotLineDoc = lineAtPos(s, Math.min(botLineBlk.to, s.doc.length));
1578
+ const visBotLine = botLineBlk.bottom >= viewportBottom ? visBotLineDoc : visBotLineDoc + Math.floor((viewportBottom - botLineBlk.bottom) / view.defaultLineHeight);
1579
+ const needsScrollTop = false;
1580
+ const needsScrollBot = mainLine >= visBotLine - cursorLineMargin2;
1581
+ if (needsScrollTop && needsScrollBot) {
1582
+ console.warn("is cursorScrollMargin too large for the editor size?");
1583
+ return;
1584
+ }
1585
+ if (!needsScrollTop && !needsScrollBot) {
1586
+ return;
1587
+ }
1588
+ if (selectionSet) {
1589
+ const { head } = startState.selection.main;
1590
+ const oldMainLine = lineAtPos(startState, head);
1591
+ if (needsScrollTop && oldMainLine < mainLine) {
1592
+ return;
1593
+ }
1594
+ if (needsScrollBot && oldMainLine > mainLine) {
1595
+ return;
1596
+ }
1597
+ }
1598
+ view.dispatch({
1599
+ annotations: Transaction.userEvent.of(annotation),
1600
+ effects: EditorView7.scrollIntoView(s.selection.main.head, {
1601
+ y: needsScrollTop ? "start" : "end",
1602
+ yMargin: view.defaultLineHeight * cursorLineMargin2
1603
+ })
1604
+ });
1605
+ });
1606
+
1607
+ // packages/ui/react-ui-editor/src/extensions/listener.ts
1608
+ import { EditorView as EditorView8 } from "@codemirror/view";
1558
1609
  var listener = ({ onFocus, onChange }) => {
1559
1610
  const extensions = [];
1560
- onFocus && extensions.push(EditorView7.focusChangeEffect.of((_, focused) => {
1611
+ onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
1561
1612
  onFocus(focused);
1562
1613
  return null;
1563
1614
  }));
1564
- onChange && extensions.push(EditorView7.updateListener.of((update2) => {
1615
+ onChange && extensions.push(EditorView8.updateListener.of((update2) => {
1565
1616
  onChange(update2.state.doc.toString());
1566
1617
  }));
1567
1618
  return extensions;
@@ -1576,7 +1627,7 @@ import { languages } from "@codemirror/language-data";
1576
1627
  import { searchKeymap } from "@codemirror/search";
1577
1628
  import { EditorState } from "@codemirror/state";
1578
1629
  import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
1579
- import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView8, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
1630
+ import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
1580
1631
  import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
1581
1632
 
1582
1633
  // packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
@@ -1770,7 +1821,7 @@ var markdownHighlightStyle = (readonly) => {
1770
1821
  // packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
1771
1822
  var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
1772
1823
  return [
1773
- lineWrapping && EditorView8.lineWrapping,
1824
+ lineWrapping && EditorView9.lineWrapping,
1774
1825
  EditorState.allowMultipleSelections.of(true),
1775
1826
  EditorState.tabSize.of(2),
1776
1827
  // https://github.com/codemirror/basic-setup
@@ -1823,9 +1874,9 @@ var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrap
1823
1874
  // packages/ui/react-ui-editor/src/extensions/markdown/code.ts
1824
1875
  import { syntaxTree } from "@codemirror/language";
1825
1876
  import { RangeSetBuilder } from "@codemirror/state";
1826
- import { ViewPlugin as ViewPlugin3, EditorView as EditorView9, Decoration as Decoration4, WidgetType as WidgetType2 } from "@codemirror/view";
1877
+ import { ViewPlugin as ViewPlugin3, EditorView as EditorView10, Decoration as Decoration4, WidgetType as WidgetType2 } from "@codemirror/view";
1827
1878
  import { mx as mx2 } from "@dxos/react-ui-theme";
1828
- var styles4 = EditorView9.baseTheme({
1879
+ var styles4 = EditorView10.baseTheme({
1829
1880
  "& .cm-code": {
1830
1881
  fontFamily: getToken("fontFamily.mono", []).join(",")
1831
1882
  },
@@ -1948,7 +1999,7 @@ var code2 = () => {
1948
1999
  import { snippet } from "@codemirror/autocomplete";
1949
2000
  import { syntaxTree as syntaxTree2 } from "@codemirror/language";
1950
2001
  import { RangeSetBuilder as RangeSetBuilder2, EditorSelection } from "@codemirror/state";
1951
- import { Decoration as Decoration5, EditorView as EditorView10, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
2002
+ import { Decoration as Decoration5, EditorView as EditorView11, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
1952
2003
  import { useState, useMemo } from "react";
1953
2004
  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;
1954
2005
  var Inline;
@@ -3024,7 +3075,7 @@ var getFormatting = (state) => {
3024
3075
  };
3025
3076
  var useFormattingState = () => {
3026
3077
  const [state, setState] = useState(null);
3027
- const observer = useMemo(() => EditorView10.updateListener.of((update2) => {
3078
+ const observer = useMemo(() => EditorView11.updateListener.of((update2) => {
3028
3079
  if (update2.docChanged || update2.selectionSet) {
3029
3080
  const newState = getFormatting(update2.state);
3030
3081
  if (!state || !compareFormatting(state, newState)) {
@@ -3089,8 +3140,8 @@ var heading2 = () => {
3089
3140
  // packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
3090
3141
  import { syntaxTree as syntaxTree4 } from "@codemirror/language";
3091
3142
  import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
3092
- import { Decoration as Decoration7, EditorView as EditorView11, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
3093
- var styles5 = EditorView11.baseTheme({
3143
+ import { Decoration as Decoration7, EditorView as EditorView12, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
3144
+ var styles5 = EditorView12.baseTheme({
3094
3145
  "& .cm-hr": {
3095
3146
  // Note that block-level decorations should not have vertical margins,
3096
3147
  borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
@@ -3144,7 +3195,7 @@ var hr = () => {
3144
3195
  // packages/ui/react-ui-editor/src/extensions/markdown/image.ts
3145
3196
  import { syntaxTree as syntaxTree5 } from "@codemirror/language";
3146
3197
  import { StateField as StateField4 } from "@codemirror/state";
3147
- import { Decoration as Decoration8, EditorView as EditorView12, WidgetType as WidgetType4 } from "@codemirror/view";
3198
+ import { Decoration as Decoration8, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
3148
3199
  var image = (options = {}) => {
3149
3200
  return StateField4.define({
3150
3201
  create: (state) => {
@@ -3171,7 +3222,7 @@ var image = (options = {}) => {
3171
3222
  add: buildDecorations4(from, to, tr.state)
3172
3223
  });
3173
3224
  },
3174
- provide: (field) => EditorView12.decorations.from(field)
3225
+ provide: (field) => EditorView13.decorations.from(field)
3175
3226
  });
3176
3227
  };
3177
3228
  var buildDecorations4 = (from, to, state) => {
@@ -3353,12 +3404,12 @@ var buildDecorations5 = (view, options) => {
3353
3404
  // packages/ui/react-ui-editor/src/extensions/markdown/table.ts
3354
3405
  import { syntaxTree as syntaxTree7 } from "@codemirror/language";
3355
3406
  import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField5 } from "@codemirror/state";
3356
- import { Decoration as Decoration10, EditorView as EditorView13, WidgetType as WidgetType6 } from "@codemirror/view";
3407
+ import { Decoration as Decoration10, EditorView as EditorView14, WidgetType as WidgetType6 } from "@codemirror/view";
3357
3408
  var table = (options = {}) => {
3358
3409
  return StateField5.define({
3359
3410
  create: (state) => update(state, options),
3360
3411
  update: (_, tr) => update(tr.state, options),
3361
- provide: (field) => EditorView13.decorations.from(field)
3412
+ provide: (field) => EditorView14.decorations.from(field)
3362
3413
  });
3363
3414
  };
3364
3415
  var update = (state, options) => {
@@ -3451,8 +3502,8 @@ var TableWidget = class extends WidgetType6 {
3451
3502
  // packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
3452
3503
  import { syntaxTree as syntaxTree8 } from "@codemirror/language";
3453
3504
  import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
3454
- import { EditorView as EditorView14, Decoration as Decoration11, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
3455
- var styles6 = EditorView14.baseTheme({
3505
+ import { EditorView as EditorView15, Decoration as Decoration11, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
3506
+ var styles6 = EditorView15.baseTheme({
3456
3507
  "& .cm-task": {
3457
3508
  color: getToken("extend.colors.blue.500")
3458
3509
  },
@@ -3575,10 +3626,10 @@ var mention = ({ onSearch }) => {
3575
3626
  };
3576
3627
 
3577
3628
  // packages/ui/react-ui-editor/src/extensions/modes.ts
3578
- import { Facet as Facet4 } from "@codemirror/state";
3629
+ import { Facet as Facet5 } from "@codemirror/state";
3579
3630
  import { keymap as keymap6 } from "@codemirror/view";
3580
3631
  import { vim } from "@replit/codemirror-vim";
3581
- var editorMode = Facet4.define({
3632
+ var editorMode = Facet5.define({
3582
3633
  combine: (modes) => modes[0] ?? {}
3583
3634
  });
3584
3635
  var EditorModes = {
@@ -3942,7 +3993,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3942
3993
  selection,
3943
3994
  extensions: [
3944
3995
  // TODO(burdon): Doesn't catch errors in keymap functions.
3945
- EditorView15.exceptionSink.of((err) => {
3996
+ EditorView16.exceptionSink.of((err) => {
3946
3997
  log3.catch(err, void 0, {
3947
3998
  F: __dxlog_file4,
3948
3999
  L: 113,
@@ -3952,17 +4003,17 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3952
4003
  }),
3953
4004
  // Theme.
3954
4005
  // TODO(burdon): Make configurable.
3955
- EditorView15.baseTheme(defaultTheme),
3956
- EditorView15.theme(theme ?? {}),
3957
- EditorView15.darkTheme.of(themeMode === "dark"),
3958
- EditorView15.editorAttributes.of({
4006
+ EditorView16.baseTheme(defaultTheme),
4007
+ EditorView16.theme(theme ?? {}),
4008
+ EditorView16.darkTheme.of(themeMode === "dark"),
4009
+ EditorView16.editorAttributes.of({
3959
4010
  class: slots.editor?.className ?? ""
3960
4011
  }),
3961
- EditorView15.contentAttributes.of({
4012
+ EditorView16.contentAttributes.of({
3962
4013
  class: slots.content?.className ?? ""
3963
4014
  }),
3964
4015
  // Focus.
3965
- EditorView15.updateListener.of((update2) => {
4016
+ EditorView16.updateListener.of((update2) => {
3966
4017
  update2.transactions.forEach((transaction) => {
3967
4018
  if (transaction.isUserEvent("focus.container")) {
3968
4019
  rootRef.current?.focus();
@@ -3970,7 +4021,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3970
4021
  });
3971
4022
  }),
3972
4023
  // State.
3973
- EditorView15.editable.of(!readonly),
4024
+ EditorView16.editable.of(!readonly),
3974
4025
  EditorState2.readOnly.of(!!readonly),
3975
4026
  // Storage and replication.
3976
4027
  // NOTE: This must come before user extensions.
@@ -3979,7 +4030,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3979
4030
  ...extensions
3980
4031
  ].filter(isNotFalsy4)
3981
4032
  });
3982
- const newView = new EditorView15({
4033
+ const newView = new EditorView16({
3983
4034
  state,
3984
4035
  parent: rootRef.current,
3985
4036
  scrollTo,
@@ -4535,7 +4586,7 @@ var useEditorView = (id) => {
4535
4586
 
4536
4587
  // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
4537
4588
  import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
4538
- import { EditorView as EditorView16 } from "@codemirror/view";
4589
+ import { EditorView as EditorView17 } from "@codemirror/view";
4539
4590
  import { useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
4540
4591
  import { log as log5 } from "@dxos/log";
4541
4592
  import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
@@ -4552,7 +4603,7 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
4552
4603
  selection,
4553
4604
  extensions: [
4554
4605
  // TODO(burdon): Doesn't catch errors in keymap functions.
4555
- EditorView16.exceptionSink.of((err) => {
4606
+ EditorView17.exceptionSink.of((err) => {
4556
4607
  log5.catch(err, void 0, {
4557
4608
  F: __dxlog_file6,
4558
4609
  L: 60,
@@ -4561,12 +4612,12 @@ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions }
4561
4612
  });
4562
4613
  }),
4563
4614
  extensions,
4564
- EditorView16.updateListener.of(() => {
4615
+ EditorView17.updateListener.of(() => {
4565
4616
  onUpdate.current?.();
4566
4617
  })
4567
4618
  ].filter(isNotFalsy5)
4568
4619
  });
4569
- view2 = new EditorView16({
4620
+ view2 = new EditorView17({
4570
4621
  parent: parentRef.current,
4571
4622
  scrollTo,
4572
4623
  state,
@@ -4624,19 +4675,19 @@ var createDataExtensions = ({ readonly = false } = {}) => {
4624
4675
  return [
4625
4676
  //
4626
4677
  EditorState3.readOnly.of(readonly),
4627
- EditorView16.editable.of(!readonly)
4678
+ EditorView17.editable.of(!readonly)
4628
4679
  ];
4629
4680
  };
4630
4681
  var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
4631
4682
  return [
4632
4683
  //
4633
- EditorView16.baseTheme(defaultTheme),
4634
- theme && EditorView16.theme(theme),
4635
- EditorView16.darkTheme.of(themeMode === "dark"),
4636
- EditorView16.editorAttributes.of({
4684
+ EditorView17.baseTheme(defaultTheme),
4685
+ theme && EditorView17.theme(theme),
4686
+ EditorView17.darkTheme.of(themeMode === "dark"),
4687
+ EditorView17.editorAttributes.of({
4637
4688
  class: slots?.editor?.className ?? ""
4638
4689
  }),
4639
- EditorView16.contentAttributes.of({
4690
+ EditorView17.contentAttributes.of({
4640
4691
  class: slots?.content?.className ?? ""
4641
4692
  })
4642
4693
  ].filter(isNotFalsy5);
@@ -4745,6 +4796,8 @@ export {
4745
4796
  createDataExtensions,
4746
4797
  createMarkdownExtensions,
4747
4798
  createThemeExtensions,
4799
+ cursorLineMargin,
4800
+ cursorLineMarginFacet,
4748
4801
  defaultMarkdownSlots,
4749
4802
  defaultOptions,
4750
4803
  defaultSlots,