@dxos/ui-editor 0.8.4-main.bc674ce → 0.8.4-main.bcb3aa67d6

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 (76) hide show
  1. package/dist/lib/browser/index.mjs +711 -521
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +711 -521
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/defaults.d.ts +3 -10
  8. package/dist/types/src/defaults.d.ts.map +1 -1
  9. package/dist/types/src/extensions/auto-scroll.d.ts +6 -0
  10. package/dist/types/src/extensions/auto-scroll.d.ts.map +1 -0
  11. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
  12. package/dist/types/src/extensions/factories.d.ts.map +1 -1
  13. package/dist/types/src/extensions/folding.d.ts.map +1 -1
  14. package/dist/types/src/extensions/index.d.ts +3 -2
  15. package/dist/types/src/extensions/index.d.ts.map +1 -1
  16. package/dist/types/src/extensions/markdown/bundle.d.ts +3 -0
  17. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  18. package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
  19. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  20. package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
  21. package/dist/types/src/extensions/markdown/styles.d.ts.map +1 -1
  22. package/dist/types/src/extensions/preview/preview.d.ts +3 -1
  23. package/dist/types/src/extensions/preview/preview.d.ts.map +1 -1
  24. package/dist/types/src/extensions/scroll-past-end.d.ts +3 -0
  25. package/dist/types/src/extensions/scroll-past-end.d.ts.map +1 -0
  26. package/dist/types/src/extensions/scroller.d.ts +66 -0
  27. package/dist/types/src/extensions/scroller.d.ts.map +1 -0
  28. package/dist/types/src/extensions/tags/streamer.d.ts +1 -1
  29. package/dist/types/src/styles/index.d.ts +0 -2
  30. package/dist/types/src/styles/index.d.ts.map +1 -1
  31. package/dist/types/src/styles/theme.d.ts +15 -0
  32. package/dist/types/src/styles/theme.d.ts.map +1 -1
  33. package/dist/types/src/util/cursor.d.ts +1 -1
  34. package/dist/types/src/util/cursor.d.ts.map +1 -1
  35. package/dist/types/tsconfig.tsbuildinfo +1 -1
  36. package/package.json +32 -32
  37. package/src/defaults.ts +19 -21
  38. package/src/extensions/annotations.ts +1 -1
  39. package/src/extensions/auto-scroll.ts +129 -0
  40. package/src/extensions/automerge/automerge.test.tsx +2 -2
  41. package/src/extensions/automerge/automerge.ts +6 -5
  42. package/src/extensions/blocks.ts +5 -5
  43. package/src/extensions/comments.ts +5 -5
  44. package/src/extensions/dnd.ts +2 -2
  45. package/src/extensions/factories.ts +7 -8
  46. package/src/extensions/folding.ts +3 -20
  47. package/src/extensions/index.ts +3 -2
  48. package/src/extensions/markdown/bundle.ts +23 -9
  49. package/src/extensions/markdown/decorate.ts +15 -11
  50. package/src/extensions/markdown/highlight.ts +15 -7
  51. package/src/extensions/markdown/link.ts +27 -33
  52. package/src/extensions/markdown/parser.test.ts +0 -1
  53. package/src/extensions/markdown/styles.ts +36 -9
  54. package/src/extensions/markdown/table.ts +24 -2
  55. package/src/extensions/outliner/outliner.ts +3 -3
  56. package/src/extensions/preview/preview.ts +62 -15
  57. package/src/extensions/scroll-past-end.ts +32 -0
  58. package/src/extensions/scroller.ts +233 -0
  59. package/src/extensions/selection.ts +1 -1
  60. package/src/extensions/tags/streamer.ts +2 -2
  61. package/src/extensions/tags/xml-tags.ts +7 -4
  62. package/src/styles/index.ts +0 -2
  63. package/src/styles/theme.ts +116 -34
  64. package/src/util/cursor.ts +1 -1
  65. package/dist/types/src/extensions/autoscroll.d.ts +0 -20
  66. package/dist/types/src/extensions/autoscroll.d.ts.map +0 -1
  67. package/dist/types/src/extensions/scrolling.d.ts +0 -78
  68. package/dist/types/src/extensions/scrolling.d.ts.map +0 -1
  69. package/dist/types/src/styles/markdown.d.ts +0 -8
  70. package/dist/types/src/styles/markdown.d.ts.map +0 -1
  71. package/dist/types/src/styles/tokens.d.ts +0 -3
  72. package/dist/types/src/styles/tokens.d.ts.map +0 -1
  73. package/src/extensions/autoscroll.ts +0 -165
  74. package/src/extensions/scrolling.ts +0 -189
  75. package/src/styles/markdown.ts +0 -26
  76. package/src/styles/tokens.ts +0 -17
@@ -0,0 +1,233 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { StateEffect } from '@codemirror/state';
6
+ import { EditorView, ViewPlugin } from '@codemirror/view';
7
+
8
+ import { log } from '@dxos/log';
9
+
10
+ /**
11
+ * Parameters for the scroll to line effect.
12
+ */
13
+ export type ScrollToProps = {
14
+ /**
15
+ * Zero-based line number; -1 for end of document.
16
+ * NOTE: view.state.doc.lineAt() uses 1-based line numbers.
17
+ */
18
+ line: number;
19
+
20
+ /**
21
+ * Additional offset from the target line in pixels.
22
+ * Positive values scroll past the line, negative values stop before it.
23
+ * @default 0
24
+ */
25
+ offset?: number;
26
+
27
+ /**
28
+ * Position of the target line in the viewport.
29
+ * - 'start': Line appears at the start (top) of the screen
30
+ * - 'end': Line appears at the end (bottom) of the screen
31
+ * @default 'start'
32
+ */
33
+ position?: 'start' | 'end';
34
+
35
+ /**
36
+ * Whether to use smooth scrolling.
37
+ * @default 'instant'
38
+ */
39
+ behavior?: ScrollBehavior;
40
+ };
41
+
42
+ /** Scroll to a specific line. */
43
+ export const scrollerLineEffect = StateEffect.define<ScrollToProps>();
44
+
45
+ /** Start/stop crawling the end of the document. */
46
+ export const scrollerCrawlEffect = StateEffect.define<boolean>();
47
+
48
+ /**
49
+ * Helper function to scroll to a specific line.
50
+ * This is a convenience function that can be used directly with an EditorView.
51
+ */
52
+ export const scrollToLine = (view: EditorView, options: ScrollToProps) => {
53
+ view.dispatch({
54
+ effects: scrollerLineEffect.of(options),
55
+ });
56
+ };
57
+
58
+ export type ScrollerOptions = {
59
+ /** Threshold in px to trigger scroll from bottom. */
60
+ overScroll?: number;
61
+ };
62
+
63
+ /**
64
+ * Extension that provides smooth scrolling to specific lines in the editor.
65
+ */
66
+ export const scroller = ({ overScroll = 0 }: ScrollerOptions = {}) => {
67
+ // ViewPlugin to manage scroll animations.
68
+ const scrollPlugin = ViewPlugin.fromClass(
69
+ class ScrollerPlugin {
70
+ private readonly crawler: ReturnType<typeof createCrawler>;
71
+ constructor(private readonly view: EditorView) {
72
+ this.crawler = createCrawler(this.view);
73
+ }
74
+
75
+ // No-op.
76
+ destroy() {
77
+ this.crawler.cancel();
78
+ }
79
+
80
+ cancel() {
81
+ this.crawler.cancel();
82
+ }
83
+
84
+ crawl(start = false) {
85
+ if (start) {
86
+ this.crawler.scroll();
87
+ } else {
88
+ this.crawler.cancel();
89
+ }
90
+ }
91
+
92
+ scroll({ line, offset = 0, position, behavior = 'instant' }: ScrollToProps) {
93
+ const { scrollTop, scrollHeight, clientHeight } = this.view.scrollDOM;
94
+ const scrollerRect = this.view.scrollDOM.getBoundingClientRect();
95
+ const doc = this.view.state.doc;
96
+
97
+ let targetScrollTop = scrollHeight - clientHeight + offset;
98
+ if (line >= 0 && line <= doc.lines - 1) {
99
+ const lineStart = doc.line(line + 1).from;
100
+ const coords = this.view.coordsAtPos(lineStart);
101
+ if (coords) {
102
+ // Calculate target scroll position based on position option.
103
+ const currentScrollTop = scrollTop;
104
+ const maxScrollTop = scrollHeight - clientHeight;
105
+
106
+ if (position === 'end') {
107
+ // Position line at end (bottom) of viewport.
108
+ // Calculate how far down we need to scroll so the line's bottom aligns with viewport bottom.
109
+ targetScrollTop = currentScrollTop + coords.bottom - scrollerRect.bottom + offset;
110
+ } else {
111
+ // Default: position line at start (top) of viewport.
112
+ targetScrollTop = currentScrollTop + coords.top - scrollerRect.top + offset;
113
+ }
114
+
115
+ // Clamp to valid scroll range.
116
+ targetScrollTop = Math.max(0, Math.min(targetScrollTop, maxScrollTop));
117
+ }
118
+ }
119
+
120
+ // TODO(burdon): Smooth scrolling doesn't work when the document is being streamed into.
121
+ requestAnimationFrame(() => {
122
+ this.view.scrollDOM.scrollTo({ top: targetScrollTop }); //, behavior });
123
+ });
124
+ }
125
+ },
126
+ );
127
+
128
+ return [
129
+ scrollPlugin,
130
+
131
+ // Listen for effect.s
132
+ EditorView.updateListener.of((update) => {
133
+ update.transactions.forEach((transaction) => {
134
+ try {
135
+ const plugin = update.view.plugin(scrollPlugin);
136
+ if (plugin) {
137
+ for (const effect of transaction.effects) {
138
+ if (effect.is(scrollerCrawlEffect)) {
139
+ plugin.crawl(effect.value);
140
+ } else if (effect.is(scrollerLineEffect)) {
141
+ plugin.scroll(effect.value);
142
+ }
143
+ }
144
+ }
145
+ } catch (err) {
146
+ log.catch(err);
147
+ }
148
+ });
149
+ }),
150
+
151
+ // Styles.
152
+ EditorView.theme({
153
+ '.cm-content': {
154
+ paddingBottom: `${overScroll}px`,
155
+ },
156
+ '.cm-scroller': {
157
+ overflowAnchor: 'none',
158
+ paddingBottom: '0',
159
+ },
160
+ '.cm-scroller.cm-hide-scrollbar::-webkit-scrollbar': {
161
+ display: 'none',
162
+ },
163
+ '.cm-scroller::-webkit-scrollbar-thumb': {
164
+ background: 'transparent',
165
+ transition: 'background 0.15s',
166
+ },
167
+ '&:hover .cm-scroller::-webkit-scrollbar-thumb': {
168
+ background: 'var(--color-scrollbar-thumb)',
169
+ },
170
+ '.cm-scroll-button': {
171
+ position: 'absolute',
172
+ bottom: '0.5rem',
173
+ right: '1rem',
174
+ },
175
+ }),
176
+ ];
177
+ };
178
+
179
+ /**
180
+ * Creates a smooth crawler that follows the live bottom of a CodeMirror 6 EditorView.
181
+ *
182
+ * Each animation frame the step is:
183
+ * step = clamp(|delta| * k, minStep, maxStep) -- but never more than |delta|
184
+ *
185
+ * Capping at |delta| is critical: it prevents overshoot, which would otherwise cause
186
+ * oscillation when the proportional step (or minStep) exceeds the remaining distance.
187
+ * The crawler settles exactly at the target with no bounce.
188
+ *
189
+ * @param k Fraction of remaining distance moved each frame (0 < k < 1).
190
+ * @param minStep Min step size in px; prevents stalling on large distances.
191
+ * @param maxStep Max step size in px.
192
+ * @param targetDelta Snap-to-target threshold in px.
193
+ */
194
+ export function createCrawler(view: EditorView, k = 0.3, maxStep = 2, targetDelta = 0.5) {
195
+ const el = view.scrollDOM;
196
+
197
+ let currentTop = 0; // Float-precision position; avoids browser integer-rounding of scrollTop.
198
+ let rafId: number | null = null;
199
+
200
+ function frame() {
201
+ // Recompute each frame so the animation chases a live-updating document's bottom.
202
+ const targetTop = el.scrollHeight - el.clientHeight;
203
+ const delta = targetTop - currentTop;
204
+ const absDelta = Math.abs(delta);
205
+ if (absDelta < targetDelta) {
206
+ el.scrollTop = targetTop;
207
+ currentTop = targetTop;
208
+ rafId = null;
209
+ return;
210
+ }
211
+
212
+ // Clamp step to [minStep, maxStep], then cap at absDelta to prevent overshoot.
213
+ const step = Math.sign(delta) * Math.min(absDelta, Math.max(1, Math.min(absDelta * k, maxStep)));
214
+ currentTop += step;
215
+ el.scrollTop = currentTop;
216
+ rafId = requestAnimationFrame(frame);
217
+ }
218
+
219
+ return {
220
+ scroll: () => {
221
+ if (rafId === null) {
222
+ currentTop = el.scrollTop;
223
+ rafId = requestAnimationFrame(frame);
224
+ }
225
+ },
226
+ cancel: () => {
227
+ if (rafId !== null) {
228
+ cancelAnimationFrame(rafId);
229
+ rafId = null;
230
+ }
231
+ },
232
+ };
233
+ }
@@ -31,7 +31,7 @@ export type EditorStateStore = {
31
31
  getState: (id: string) => EditorSelectionState | undefined;
32
32
  };
33
33
 
34
- const stateRestoreAnnotation = 'dxos.org/cm/state-restore';
34
+ const stateRestoreAnnotation = 'org.dxos.cm.state-restore';
35
35
 
36
36
  export const createEditorStateTransaction = ({ scrollTo, selection }: EditorSelectionState): TransactionSpec => {
37
37
  return {
@@ -17,7 +17,7 @@ export type StreamerOptions = {
17
17
  };
18
18
 
19
19
  /**
20
- * Extension that adds a blinking cursor widget at the end of the document.
20
+ * Extension that animates streaming content.
21
21
  */
22
22
  export const streamer = (options: StreamerOptions = {}): Extension => {
23
23
  return [
@@ -114,7 +114,7 @@ class CursorWidget extends WidgetType {
114
114
  */
115
115
  const fadeIn = (options: { removalDelay?: number } = {}): Extension => {
116
116
  const FADE_IN_DURATION = 1_000; // ms.
117
- const DEFAULT_REMOVAL_DELAY = 5_000; // ms.
117
+ const DEFAULT_REMOVAL_DELAY = 3_000; // ms.
118
118
  const removalDelay = options.removalDelay ?? DEFAULT_REMOVAL_DELAY;
119
119
 
120
120
  // Effect to remove a specific decoration by range.
@@ -21,7 +21,7 @@ import { log } from '@dxos/log';
21
21
 
22
22
  import { type Range } from '../../types';
23
23
  import { decorationSetToArray } from '../../util';
24
- import { scrollToLineEffect } from '../scrolling';
24
+ import { scrollerLineEffect } from '../scroller';
25
25
 
26
26
  import { nodeToJson } from './xml-util';
27
27
 
@@ -268,7 +268,7 @@ const createNavigationEffectPlugin = (
268
268
  const line = view.state.doc.lineAt(widget?.from ?? 0);
269
269
  view.dispatch({
270
270
  selection: { anchor: line.from, head: line.from },
271
- effects: scrollToLineEffect.of({ line: line.number, options: { offset: -16 } }),
271
+ effects: scrollerLineEffect.of({ line: line.number - 1, offset: -16 }),
272
272
  });
273
273
 
274
274
  continue;
@@ -294,13 +294,13 @@ const createNavigationEffectPlugin = (
294
294
  const line = view.state.doc.lineAt(widget?.from);
295
295
  view.dispatch({
296
296
  selection: { anchor: line.to, head: line.to },
297
- effects: scrollToLineEffect.of({ line: line.number, options: { offset: -16 } }),
297
+ effects: scrollerLineEffect.of({ line: line.number - 1, offset: -16 }),
298
298
  });
299
299
  } else {
300
300
  const line = view.state.doc.lineAt(view.state.doc.length);
301
301
  view.dispatch({
302
302
  selection: { anchor: line.to, head: line.to },
303
- effects: scrollToLineEffect.of({ line: line.number, options: { position: 'end' } }),
303
+ effects: scrollerLineEffect.of({ line: line.number - 1, position: 'end' }),
304
304
  });
305
305
  }
306
306
 
@@ -359,6 +359,9 @@ const createWidgetDecorationsField = (registry: XmlWidgetRegistry = {}, notifier
359
359
  // Check for reset effect.
360
360
  for (const effect of tr.effects) {
361
361
  if (effect.is(xmlTagResetEffect)) {
362
+ if (tr.docChanged) {
363
+ return buildDecorations(tr.state, { from: 0, to: tr.state.doc.length }, registry, notifier);
364
+ }
362
365
  return { from: 0, decorations: Decoration.none };
363
366
  }
364
367
  }
@@ -2,6 +2,4 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- export * from './markdown';
6
5
  export * from './theme';
7
- export * from './tokens';
@@ -5,7 +5,60 @@
5
5
  import { type Extension } from '@codemirror/state';
6
6
  import { EditorView } from '@codemirror/view';
7
7
 
8
- import { fontBody, fontMono } from './tokens';
8
+ import { mx } from '@dxos/ui-theme';
9
+
10
+ export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
11
+
12
+ // https://tailwindcss.com/docs/font-weight
13
+ const headings: Record<HeadingLevel, { className: string; fontSize: string; lineHeight: string }> = {
14
+ 1: {
15
+ className: 'text-3xl',
16
+ fontSize: 'var(--text-3xl)',
17
+ lineHeight: 'var(--text-4xl--line-height)',
18
+ },
19
+ 2: {
20
+ className: 'text-2xl',
21
+ fontSize: 'var(--text-2xl)',
22
+ lineHeight: 'var(--text-3xl--line-height)',
23
+ },
24
+ 3: {
25
+ className: 'text-xl',
26
+ fontSize: 'var(--text-xl)',
27
+ lineHeight: 'var(--text-2xl--line-height)',
28
+ },
29
+ 4: {
30
+ className: 'text-lg',
31
+ fontSize: 'var(--text-lg)',
32
+ lineHeight: 'var(--text-xl--line-height)',
33
+ },
34
+ 5: {
35
+ className: 'text-base',
36
+ fontSize: 'var(--text-base)',
37
+ lineHeight: 'var(--text-lg--line-height)',
38
+ },
39
+ 6: {
40
+ className: 'text-base',
41
+ fontSize: 'var(--text-base)',
42
+ lineHeight: 'var(--text-base--line-height)',
43
+ },
44
+ };
45
+
46
+ // Font families matching --font-body and --font-mono in theme.css.
47
+ export const fontBody = '"Inter Variable", ui-sans-serif, system-ui, sans-serif';
48
+ export const fontMono = '"JetBrains Mono Variable", ui-monospace, "Cascadia Code", "Source Code Pro", monospace';
49
+
50
+ export const markdownTheme = {
51
+ code: 'font-mono! cm-code-inline',
52
+ codeMark: 'font-mono! cm-code-mark',
53
+ mark: 'font-mono!',
54
+ heading: (level: HeadingLevel) => ({
55
+ className: mx(headings[level].className, 'font-light text-(--color-cm-heading-number)'),
56
+ color: 'var(--color-cm-heading) !important',
57
+ lineHeight: headings[level].lineHeight,
58
+ fontSize: headings[level].fontSize,
59
+ fontWeight: '100 !important',
60
+ }),
61
+ };
9
62
 
10
63
  /**
11
64
  * Global base theme.
@@ -43,6 +96,9 @@ import { fontBody, fontMono } from './tokens';
43
96
  * </div>
44
97
  */
45
98
  export const baseTheme = EditorView.baseTheme({
99
+ /**
100
+ * Outer frame.
101
+ */
46
102
  '&': {},
47
103
  '&.cm-focused': {
48
104
  outline: 'none',
@@ -52,7 +108,18 @@ export const baseTheme = EditorView.baseTheme({
52
108
  * Scroller
53
109
  */
54
110
  '.cm-scroller': {
55
- overflowY: 'auto',
111
+ overflowAnchor: 'none',
112
+ },
113
+ '.cm-scroller::-webkit-scrollbar': {
114
+ width: '8px',
115
+ },
116
+ '.cm-scroller::-webkit-scrollbar-track': {},
117
+ '.cm-scroller::-webkit-scrollbar-thumb': {
118
+ background: 'transparent',
119
+ transition: 'background 0.15s',
120
+ },
121
+ '&:hover .cm-scroller::-webkit-scrollbar-thumb': {
122
+ background: 'var(--color-scrollbar-thumb)',
56
123
  },
57
124
 
58
125
  /**
@@ -61,7 +128,6 @@ export const baseTheme = EditorView.baseTheme({
61
128
  */
62
129
  '.cm-content': {
63
130
  padding: 'unset',
64
- lineHeight: '24px',
65
131
  color: 'unset',
66
132
  },
67
133
 
@@ -76,8 +142,8 @@ export const baseTheme = EditorView.baseTheme({
76
142
  '.cm-gutter': {},
77
143
  '.cm-gutter.cm-lineNumbers': {
78
144
  paddingRight: '4px',
79
- borderRight: '1px solid var(--dx-subduedSeparator)',
80
- color: 'var(--dx-subduedText)',
145
+ borderRight: '1px solid var(--color-subdued-separator)',
146
+ color: 'var(--color-subdued)',
81
147
  },
82
148
  '.cm-gutter.cm-lineNumbers .cm-gutterElement': {
83
149
  minWidth: '40px',
@@ -86,7 +152,7 @@ export const baseTheme = EditorView.baseTheme({
86
152
  * Height is set to match the corresponding line (which may have wrapped).
87
153
  */
88
154
  '.cm-gutterElement': {
89
- lineHeight: '24px',
155
+ lineHeight: 1.5,
90
156
  fontSize: '12px',
91
157
  },
92
158
 
@@ -94,31 +160,38 @@ export const baseTheme = EditorView.baseTheme({
94
160
  * Line.
95
161
  */
96
162
  '.cm-line': {
97
- lineHeight: '24px',
163
+ lineHeight: 1.5,
98
164
  paddingInline: 0,
99
165
  },
166
+ /**
167
+ * Force all inline children to inherit line-height to prevent monospace font metrics
168
+ * (JetBrains Mono ascent/descent) from inflating the line box beyond 24px.
169
+ */
170
+ '.cm-line *': {
171
+ lineHeight: 'inherit',
172
+ },
100
173
  '.cm-activeLine': {
101
- background: 'var(--dx-cmActiveLine)',
174
+ background: 'var(--color-cm-active-line)',
102
175
  },
103
176
 
104
177
  /**
105
178
  * Cursor (layer).
106
179
  */
107
180
  '.cm-cursor, .cm-dropCursor': {
108
- borderLeft: '2px solid var(--dx-cmCursor)',
181
+ borderLeft: '2px solid var(--color-cm-cursor)',
109
182
  },
110
183
  '.cm-placeholder': {
111
- color: 'var(--dx-placeholder)',
184
+ color: 'var(--color-placeholder)',
112
185
  },
113
186
 
114
187
  /**
115
188
  * Selection (layer).
116
189
  */
117
190
  '.cm-selectionBackground': {
118
- background: 'var(--dx-cmSelection)',
191
+ background: 'var(--color-cm-selection)',
119
192
  },
120
193
  '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground': {
121
- background: 'var(--dx-cmFocusedSelection)',
194
+ background: 'var(--color-cm-focused-selection)',
122
195
  },
123
196
 
124
197
  /**
@@ -129,8 +202,8 @@ export const baseTheme = EditorView.baseTheme({
129
202
  margin: '0 -3px',
130
203
  padding: '3px',
131
204
  borderRadius: '3px',
132
- background: 'var(--dx-cmHighlightSurface)',
133
- color: 'var(--dx-cmHighlight)',
205
+ background: 'var(--color-cm-highlight-surface)',
206
+ color: 'var(--color-cm-highlight)',
134
207
  },
135
208
  '.cm-searchMatch-selected': {
136
209
  textDecoration: 'underline',
@@ -142,21 +215,30 @@ export const baseTheme = EditorView.baseTheme({
142
215
  '.cm-link': {
143
216
  textDecorationLine: 'underline',
144
217
  textDecorationThickness: '1px',
145
- textDecorationColor: 'var(--dx-separator)',
218
+ textDecorationColor: 'var(--color-separator)',
146
219
  textUnderlineOffset: '2px',
147
220
  borderRadius: '.125rem',
148
221
  },
149
222
  '.cm-link > span': {
150
- color: 'var(--dx-accentText)',
223
+ color: 'var(--color-accent-text)',
224
+ },
225
+ '.cm-link > span:hover': {
226
+ color: 'var(--color-accent-text-hover)',
151
227
  },
152
228
 
153
229
  /**
154
230
  * Tooltip.
155
231
  */
156
232
  '.cm-tooltip': {
157
- background: 'var(--dx-baseSurface)',
233
+ background: 'var(--color-modal-surface)',
158
234
  },
159
235
  '.cm-tooltip-below': {},
236
+ '.cm-tooltip-hover': {
237
+ background: 'var(--color-modal-surface)',
238
+ border: '1px solid var(--color-separator)',
239
+ borderRadius: '4px',
240
+ overflow: 'hidden',
241
+ },
160
242
 
161
243
  /**
162
244
  * Autocomplete.
@@ -165,7 +247,7 @@ export const baseTheme = EditorView.baseTheme({
165
247
  '.cm-tooltip.cm-tooltip-autocomplete': {
166
248
  marginTop: '6px',
167
249
  marginLeft: '-10px',
168
- border: '2px solid var(--dx-separator)',
250
+ border: '2px solid var(--color-separator)',
169
251
  borderRadius: '4px',
170
252
  },
171
253
  '.cm-tooltip.cm-tooltip-autocomplete > ul': {
@@ -175,12 +257,12 @@ export const baseTheme = EditorView.baseTheme({
175
257
  padding: '4px',
176
258
  },
177
259
  '.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {
178
- background: 'var(--dx-activeSurface)',
179
- color: 'var(--dx-activeSurfaceText)',
260
+ background: 'var(--color-active-surface)',
261
+ color: 'var(--color-base-surface-text)',
180
262
  },
181
263
  '.cm-tooltip.cm-tooltip-autocomplete > ul > completion-section': {
182
264
  paddingLeft: '4px !important',
183
- color: 'var(--dx-hoverSurfaceText)',
265
+ color: 'var(--color-base-surface-text)',
184
266
  },
185
267
 
186
268
  /**
@@ -190,17 +272,17 @@ export const baseTheme = EditorView.baseTheme({
190
272
  width: '360px !important',
191
273
  margin: '-10px 1px 0 1px',
192
274
  padding: '8px !important',
193
- borderColor: 'var(--dx-separator)',
275
+ borderColor: 'var(--color-separator)',
194
276
  },
195
277
  '.cm-completionIcon': {
196
278
  display: 'none',
197
279
  },
198
280
  '.cm-completionLabel': {
199
- color: 'var(--dx-description)',
281
+ color: 'var(--color-description)',
200
282
  padding: '0 4px',
201
283
  },
202
284
  '.cm-completionMatchedText': {
203
- color: 'var(--dx-baseText)',
285
+ color: 'var(--color-base-surface-text)',
204
286
  textDecoration: 'none !important',
205
287
  },
206
288
 
@@ -225,7 +307,7 @@ export const baseTheme = EditorView.baseTheme({
225
307
  backgroundColor: 'var(--surface-bg)',
226
308
  },
227
309
  '.cm-panel input, .cm-panel button, .cm-panel label': {
228
- color: 'var(--dx-subdued)',
310
+ color: 'var(--color-subdued)',
229
311
  fontSize: '14px',
230
312
  all: 'unset',
231
313
  margin: '3px !important',
@@ -233,10 +315,10 @@ export const baseTheme = EditorView.baseTheme({
233
315
  outline: '1px solid transparent',
234
316
  },
235
317
  '.cm-panel input, .cm-panel button': {
236
- backgroundColor: 'var(--dx-inputSurface)',
318
+ backgroundColor: 'var(--color-input-surface)',
237
319
  },
238
320
  '.cm-panel input:focus, .cm-panel button:focus': {
239
- outline: '1px solid var(--dx-neutralFocusIndicator)',
321
+ outline: '1px solid var(--color-neutral-focus-indicator)',
240
322
  },
241
323
  '.cm-panel label': {
242
324
  display: 'inline-flex',
@@ -249,26 +331,27 @@ export const baseTheme = EditorView.baseTheme({
249
331
  height: '8px',
250
332
  marginRight: '6px !important',
251
333
  padding: '2px !important',
252
- color: 'var(--dx-neutralFocusIndicator)',
334
+ color: 'var(--color-neutral-focus-indicator)',
253
335
  },
254
336
  '.cm-panel button': {
255
337
  '&:hover': {
256
- backgroundColor: 'var(--dx-accentSurfaceHover) !important',
338
+ // TODO(burdon): Replace with layer and @apply bg-accent-surface-hover
339
+ backgroundColor: 'var(--color-accent-surface-hover) !important',
257
340
  },
258
341
  '&:active': {
259
- backgroundColor: 'var(--dx-accentSurfaceHover)',
342
+ backgroundColor: 'var(--color-accent-surface-hover)',
260
343
  },
261
344
  },
262
345
  '.cm-panel.cm-search': {
263
346
  padding: '4px',
264
- borderTop: '1px solid var(--dx-separator)',
347
+ borderTop: '1px solid var(--color-separator)',
265
348
  },
266
349
  });
267
350
 
268
351
  export const editorGutter: Extension = EditorView.theme({
269
352
  '.cm-gutters': {
270
353
  // NOTE: Non-transparent background required to cover content if scrolling horizontally.
271
- background: 'var(--dx-baseSurface) !important',
354
+ background: 'var(--color-base-surface) !important',
272
355
  paddingRight: '1rem',
273
356
  },
274
357
  });
@@ -279,10 +362,9 @@ export type FontOptions = {
279
362
 
280
363
  export const createFontTheme = ({ monospace }: FontOptions = {}) =>
281
364
  EditorView.theme({
282
- // Set metrics on the scroller (this is often what CM uses for layout).
365
+ // Main content.
283
366
  '.cm-scroller': {
284
367
  fontFamily: monospace ? fontMono : fontBody,
285
- fontSize: '16px',
286
368
  },
287
369
 
288
370
  // Maintain defaults for UI components.
@@ -26,7 +26,7 @@ export const overlap = (a: Range, b: Range): boolean => a.from <= b.to && a.to >
26
26
  * while positive - with the next one.
27
27
  */
28
28
  export interface CursorConverter {
29
- toCursor(position: number, assoc?: -1 | 1 | undefined): string;
29
+ toCursor(position: number, assoc?: -1 | 1): string;
30
30
  fromCursor(cursor: string): number;
31
31
  }
32
32
 
@@ -1,20 +0,0 @@
1
- import { EditorView } from '@codemirror/view';
2
- export declare const scrollToBottomEffect: import("@codemirror/state").StateEffectType<ScrollBehavior | undefined>;
3
- export type AutoScrollOptions = {
4
- /** Auto-scroll when reaches the bottom. */
5
- autoScroll?: boolean;
6
- /** Threshold in px to trigger scroll from bottom. */
7
- threshold?: number;
8
- /** Throttle time in ms. */
9
- throttleDelay?: number;
10
- /** Callback when auto-scrolling. */
11
- onAutoScroll?: (props: {
12
- view: EditorView;
13
- distanceFromBottom: number;
14
- }) => boolean | void;
15
- };
16
- /**
17
- * Extension that supports pinning the scroll position and automatically scrolls to the bottom when content is added.
18
- */
19
- export declare const autoScroll: ({ autoScroll, threshold, throttleDelay, onAutoScroll, }?: Partial<AutoScrollOptions>) => import("@codemirror/state").Extension[];
20
- //# sourceMappingURL=autoscroll.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"autoscroll.d.ts","sourceRoot":"","sources":["../../../../src/extensions/autoscroll.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAc,MAAM,kBAAkB,CAAC;AAQ1D,eAAO,MAAM,oBAAoB,yEAAmD,CAAC;AAErF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oCAAoC;IACpC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,GAAG,IAAI,CAAC;CAC5F,CAAC;AAEF;;GAEG;AAEH,eAAO,MAAM,UAAU,GAAI,0DAKxB,OAAO,CAAC,iBAAiB,CAAM,4CAiIjC,CAAC"}