@dxos/ui-editor 0.8.4-main.bc674ce → 0.8.4-main.c85a9c8dae
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +483 -417
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +483 -417
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/defaults.d.ts +1 -1
- package/dist/types/src/defaults.d.ts.map +1 -1
- package/dist/types/src/extensions/auto-scroll.d.ts +6 -0
- package/dist/types/src/extensions/auto-scroll.d.ts.map +1 -0
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +2 -2
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/dist/types/src/extensions/preview/preview.d.ts +1 -1
- package/dist/types/src/extensions/scroller.d.ts +66 -0
- package/dist/types/src/extensions/scroller.d.ts.map +1 -0
- package/dist/types/src/styles/index.d.ts +0 -2
- package/dist/types/src/styles/index.d.ts.map +1 -1
- package/dist/types/src/styles/theme.d.ts +15 -0
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/util/cursor.d.ts +1 -1
- package/dist/types/src/util/cursor.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -32
- package/src/defaults.ts +4 -4
- package/src/extensions/annotations.ts +1 -1
- package/src/extensions/auto-scroll.ts +126 -0
- package/src/extensions/automerge/automerge.test.tsx +2 -2
- package/src/extensions/blocks.ts +5 -5
- package/src/extensions/comments.ts +5 -5
- package/src/extensions/dnd.ts +2 -2
- package/src/extensions/factories.ts +6 -7
- package/src/extensions/folding.ts +2 -2
- package/src/extensions/index.ts +2 -2
- package/src/extensions/markdown/decorate.ts +4 -3
- package/src/extensions/markdown/highlight.ts +25 -11
- package/src/extensions/markdown/link.ts +27 -33
- package/src/extensions/markdown/styles.ts +6 -6
- package/src/extensions/outliner/outliner.ts +3 -3
- package/src/extensions/preview/preview.ts +8 -8
- package/src/extensions/scroller.ts +232 -0
- package/src/extensions/tags/streamer.ts +1 -1
- package/src/extensions/tags/xml-tags.ts +7 -4
- package/src/styles/index.ts +0 -2
- package/src/styles/theme.ts +106 -29
- package/src/util/cursor.ts +1 -1
- package/dist/types/src/extensions/autoscroll.d.ts +0 -20
- package/dist/types/src/extensions/autoscroll.d.ts.map +0 -1
- package/dist/types/src/extensions/scrolling.d.ts +0 -78
- package/dist/types/src/extensions/scrolling.d.ts.map +0 -1
- package/dist/types/src/styles/markdown.d.ts +0 -8
- package/dist/types/src/styles/markdown.d.ts.map +0 -1
- package/dist/types/src/styles/tokens.d.ts +0 -3
- package/dist/types/src/styles/tokens.d.ts.map +0 -1
- package/src/extensions/autoscroll.ts +0 -165
- package/src/extensions/scrolling.ts +0 -189
- package/src/styles/markdown.ts +0 -26
- package/src/styles/tokens.ts +0 -17
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { EditorView } from '@codemirror/view';
|
|
2
|
-
/**
|
|
3
|
-
* Configuration options for smooth scrolling behavior.
|
|
4
|
-
*/
|
|
5
|
-
export type SmoothScrollOptions = {
|
|
6
|
-
/**
|
|
7
|
-
* Additional offset from the target line in pixels.
|
|
8
|
-
* Positive values scroll past the line, negative values stop before it.
|
|
9
|
-
* @default 0
|
|
10
|
-
*/
|
|
11
|
-
offset?: number;
|
|
12
|
-
/**
|
|
13
|
-
* Position of the target line in the viewport.
|
|
14
|
-
* - 'start': Line appears at the start (top) of the screen
|
|
15
|
-
* - 'end': Line appears at the end (bottom) of the screen
|
|
16
|
-
* @default 'start'
|
|
17
|
-
*/
|
|
18
|
-
position?: 'start' | 'end';
|
|
19
|
-
/**
|
|
20
|
-
* Whether to use smooth scrolling.
|
|
21
|
-
* @default 'smooth'
|
|
22
|
-
*/
|
|
23
|
-
behavior?: ScrollBehavior;
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* Parameters for the scroll to line effect.
|
|
27
|
-
*/
|
|
28
|
-
export type ScrollToLineProps = {
|
|
29
|
-
/**
|
|
30
|
-
* The line number to scroll to (1-based).
|
|
31
|
-
*/
|
|
32
|
-
line: number;
|
|
33
|
-
/**
|
|
34
|
-
* Optional configuration to override default scroll behavior.
|
|
35
|
-
*/
|
|
36
|
-
options?: SmoothScrollOptions;
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* StateEffect for triggering smooth scroll to a specific line.
|
|
40
|
-
*/
|
|
41
|
-
export declare const scrollToLineEffect: import("@codemirror/state").StateEffectType<ScrollToLineProps>;
|
|
42
|
-
/**
|
|
43
|
-
* Extension that provides smooth scrolling to specific lines in the editor.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```typescript
|
|
47
|
-
* // Add to editor extensions.
|
|
48
|
-
* const extensions = [
|
|
49
|
-
* smoothScroll()
|
|
50
|
-
* ];
|
|
51
|
-
*
|
|
52
|
-
* // Trigger scroll to line 42.
|
|
53
|
-
* view.dispatch({
|
|
54
|
-
* effects: scrollToLineEffect.of({ line: 42 })
|
|
55
|
-
* });
|
|
56
|
-
*
|
|
57
|
-
* // Scroll with custom options.
|
|
58
|
-
* view.dispatch({
|
|
59
|
-
* effects: scrollToLineEffect.of({ line: 100, options: { offset: -50 } })
|
|
60
|
-
* });
|
|
61
|
-
*
|
|
62
|
-
* // Scroll so line appears at end (bottom) of screen.
|
|
63
|
-
* view.dispatch({
|
|
64
|
-
* effects: scrollToLineEffect.of({ line: 50, options: { position: 'end' } })
|
|
65
|
-
* });
|
|
66
|
-
* ```
|
|
67
|
-
*/
|
|
68
|
-
export declare const smoothScroll: ({ offset, position }?: Partial<SmoothScrollOptions>) => import("@codemirror/state").Extension[];
|
|
69
|
-
/**
|
|
70
|
-
* Helper function to scroll to a specific line.
|
|
71
|
-
* This is a convenience function that can be used directly with an EditorView.
|
|
72
|
-
*
|
|
73
|
-
* @param view - The CodeMirror EditorView instance
|
|
74
|
-
* @param line - The line number to scroll to (1-based)
|
|
75
|
-
* @param options - Optional scroll configuration
|
|
76
|
-
*/
|
|
77
|
-
export declare const scrollToLine: (view: EditorView, line: number, options?: SmoothScrollOptions) => void;
|
|
78
|
-
//# sourceMappingURL=scrolling.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scrolling.d.ts","sourceRoot":"","sources":["../../../../src/extensions/scrolling.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAc,MAAM,kBAAkB,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,gEAA0C,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,YAAY,GAAI,uBAAoC,OAAO,CAAC,mBAAmB,CAAM,4CAkGjG,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,UAAU,EAAE,MAAM,MAAM,EAAE,UAAU,mBAAmB,SAIzF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../../src/styles/markdown.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAYjD,eAAO,MAAM,aAAa;;;;qBAIP,YAAY;CAG9B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../../src/styles/tokens.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,QAAQ,QAA8B,CAAC;AACpD,eAAO,MAAM,QAAQ,QAA8B,CAAC"}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { StateEffect } from '@codemirror/state';
|
|
6
|
-
import { EditorView, ViewPlugin } from '@codemirror/view';
|
|
7
|
-
|
|
8
|
-
import { debounce } from '@dxos/async';
|
|
9
|
-
import { Domino } from '@dxos/ui';
|
|
10
|
-
|
|
11
|
-
import { scrollToLineEffect } from './scrolling';
|
|
12
|
-
|
|
13
|
-
// TODO(burdon): Reconcile with scrollToLineEffect (scrolling).
|
|
14
|
-
export const scrollToBottomEffect = StateEffect.define<ScrollBehavior | undefined>();
|
|
15
|
-
|
|
16
|
-
export type AutoScrollOptions = {
|
|
17
|
-
/** Auto-scroll when reaches the bottom. */
|
|
18
|
-
autoScroll?: boolean;
|
|
19
|
-
/** Threshold in px to trigger scroll from bottom. */
|
|
20
|
-
threshold?: number;
|
|
21
|
-
/** Throttle time in ms. */
|
|
22
|
-
throttleDelay?: number;
|
|
23
|
-
/** Callback when auto-scrolling. */
|
|
24
|
-
onAutoScroll?: (props: { view: EditorView; distanceFromBottom: number }) => boolean | void;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Extension that supports pinning the scroll position and automatically scrolls to the bottom when content is added.
|
|
29
|
-
*/
|
|
30
|
-
// TODO(burdon): Reconcile with transcript-extension.
|
|
31
|
-
export const autoScroll = ({
|
|
32
|
-
autoScroll = true,
|
|
33
|
-
threshold = 100,
|
|
34
|
-
throttleDelay = 1_000,
|
|
35
|
-
onAutoScroll,
|
|
36
|
-
}: Partial<AutoScrollOptions> = {}) => {
|
|
37
|
-
let buttonContainer: HTMLDivElement | undefined;
|
|
38
|
-
let hideTimeout: NodeJS.Timeout | undefined;
|
|
39
|
-
let lastScrollTop = 0;
|
|
40
|
-
let isPinned = true;
|
|
41
|
-
|
|
42
|
-
const setPinned = (pin: boolean) => {
|
|
43
|
-
isPinned = pin;
|
|
44
|
-
buttonContainer?.classList.toggle('opacity-0', pin);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
// Temporarily hide the scrollbar while auto-scrolling.
|
|
48
|
-
const hideScrollbar = (view: EditorView) => {
|
|
49
|
-
view.scrollDOM.classList.add('cm-hide-scrollbar');
|
|
50
|
-
clearTimeout(hideTimeout);
|
|
51
|
-
hideTimeout = setTimeout(() => {
|
|
52
|
-
view.scrollDOM.classList.remove('cm-hide-scrollbar');
|
|
53
|
-
}, 1_000);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
// Throttled scroll to bottom.
|
|
57
|
-
const scrollToBottom = (view: EditorView, behavior?: ScrollBehavior) => {
|
|
58
|
-
setPinned(true);
|
|
59
|
-
hideScrollbar(view);
|
|
60
|
-
const line = view.state.doc.lineAt(view.state.doc.length);
|
|
61
|
-
view.dispatch({
|
|
62
|
-
selection: { anchor: line.to, head: line.to },
|
|
63
|
-
effects: scrollToLineEffect.of({
|
|
64
|
-
line: line.number,
|
|
65
|
-
options: { position: 'end', offset: threshold, behavior },
|
|
66
|
-
}),
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// Throttled check for distance from bottom (for downward scrolls only).
|
|
71
|
-
const checkDistance = debounce((view: EditorView) => {
|
|
72
|
-
const scrollerRect = view.scrollDOM.getBoundingClientRect();
|
|
73
|
-
const coords = view.coordsAtPos(view.state.doc.length);
|
|
74
|
-
const distanceFromBottom = coords ? coords.bottom - scrollerRect.bottom : 0;
|
|
75
|
-
setPinned(distanceFromBottom < 0);
|
|
76
|
-
}, 1_000);
|
|
77
|
-
|
|
78
|
-
// Debounce scroll updates so rapid edits don't cause clunky scrolling.
|
|
79
|
-
const triggerUpdate = debounce((view: EditorView) => scrollToBottom(view), throttleDelay);
|
|
80
|
-
|
|
81
|
-
return [
|
|
82
|
-
// Update listener for logging when scrolling is needed.
|
|
83
|
-
EditorView.updateListener.of(({ view, transactions, heightChanged }) => {
|
|
84
|
-
// TODO(burdon): Remove and use scrollToLineEffect instead.
|
|
85
|
-
transactions.forEach((transaction) => {
|
|
86
|
-
for (const effect of transaction.effects) {
|
|
87
|
-
if (effect.is(scrollToBottomEffect)) {
|
|
88
|
-
scrollToBottom(view, effect.value);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Maybe scroll if doc changed and pinned.
|
|
94
|
-
// NOTE: Geometry changed is triggered when widgets change height (e.g., toggle tool block).
|
|
95
|
-
if (heightChanged && isPinned) {
|
|
96
|
-
const coords = view.coordsAtPos(view.state.doc.length);
|
|
97
|
-
const scrollerRect = view.scrollDOM.getBoundingClientRect();
|
|
98
|
-
const distanceFromBottom = coords ? scrollerRect.bottom - coords.bottom : 0;
|
|
99
|
-
if (autoScroll && distanceFromBottom < threshold) {
|
|
100
|
-
const shouldScroll = onAutoScroll?.({ view, distanceFromBottom }) ?? true;
|
|
101
|
-
if (shouldScroll) {
|
|
102
|
-
triggerUpdate(view);
|
|
103
|
-
}
|
|
104
|
-
} else if (distanceFromBottom < 0) {
|
|
105
|
-
setPinned(false);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}),
|
|
109
|
-
|
|
110
|
-
// Detect user scroll.
|
|
111
|
-
EditorView.domEventHandlers({
|
|
112
|
-
scroll: (event, view) => {
|
|
113
|
-
const currentScrollTop = view.scrollDOM.scrollTop;
|
|
114
|
-
const scrollingUp = currentScrollTop < lastScrollTop;
|
|
115
|
-
lastScrollTop = currentScrollTop;
|
|
116
|
-
|
|
117
|
-
// If user scrolls up, immediately unpin auto-scroll.
|
|
118
|
-
if (scrollingUp) {
|
|
119
|
-
setPinned(false);
|
|
120
|
-
} else {
|
|
121
|
-
checkDistance(view);
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
}),
|
|
125
|
-
|
|
126
|
-
// Scroll button.
|
|
127
|
-
ViewPlugin.fromClass(
|
|
128
|
-
class {
|
|
129
|
-
constructor(view: EditorView) {
|
|
130
|
-
const icon = Domino.of('dx-icon' as any).attributes({ icon: 'ph--arrow-down--regular' });
|
|
131
|
-
const button = Domino.of('button')
|
|
132
|
-
.classNames('dx-button bg-accentSurface')
|
|
133
|
-
.attributes({ 'data-density': 'fine' })
|
|
134
|
-
.children(icon)
|
|
135
|
-
.on('click', () => {
|
|
136
|
-
scrollToBottom(view);
|
|
137
|
-
});
|
|
138
|
-
buttonContainer = Domino.of('div')
|
|
139
|
-
.classNames('cm-scroll-button transition-opacity duration-300 opacity-0')
|
|
140
|
-
.children(button).root as HTMLDivElement;
|
|
141
|
-
|
|
142
|
-
view.scrollDOM.parentElement!.appendChild(buttonContainer);
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
),
|
|
146
|
-
|
|
147
|
-
// Styles.
|
|
148
|
-
EditorView.theme({
|
|
149
|
-
'.cm-scroller': {
|
|
150
|
-
scrollbarWidth: 'thin',
|
|
151
|
-
},
|
|
152
|
-
'.cm-scroller.cm-hide-scrollbar': {
|
|
153
|
-
scrollbarWidth: 'none',
|
|
154
|
-
},
|
|
155
|
-
'.cm-scroller.cm-hide-scrollbar::-webkit-scrollbar': {
|
|
156
|
-
display: 'none',
|
|
157
|
-
},
|
|
158
|
-
'.cm-scroll-button': {
|
|
159
|
-
position: 'absolute',
|
|
160
|
-
bottom: '0.5rem',
|
|
161
|
-
right: '1rem',
|
|
162
|
-
},
|
|
163
|
-
}),
|
|
164
|
-
];
|
|
165
|
-
};
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { StateEffect } from '@codemirror/state';
|
|
6
|
-
import { EditorView, ViewPlugin } from '@codemirror/view';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Configuration options for smooth scrolling behavior.
|
|
10
|
-
*/
|
|
11
|
-
export type SmoothScrollOptions = {
|
|
12
|
-
/**
|
|
13
|
-
* Additional offset from the target line in pixels.
|
|
14
|
-
* Positive values scroll past the line, negative values stop before it.
|
|
15
|
-
* @default 0
|
|
16
|
-
*/
|
|
17
|
-
offset?: number;
|
|
18
|
-
/**
|
|
19
|
-
* Position of the target line in the viewport.
|
|
20
|
-
* - 'start': Line appears at the start (top) of the screen
|
|
21
|
-
* - 'end': Line appears at the end (bottom) of the screen
|
|
22
|
-
* @default 'start'
|
|
23
|
-
*/
|
|
24
|
-
position?: 'start' | 'end';
|
|
25
|
-
/**
|
|
26
|
-
* Whether to use smooth scrolling.
|
|
27
|
-
* @default 'smooth'
|
|
28
|
-
*/
|
|
29
|
-
behavior?: ScrollBehavior;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Parameters for the scroll to line effect.
|
|
34
|
-
*/
|
|
35
|
-
export type ScrollToLineProps = {
|
|
36
|
-
/**
|
|
37
|
-
* The line number to scroll to (1-based).
|
|
38
|
-
*/
|
|
39
|
-
line: number;
|
|
40
|
-
/**
|
|
41
|
-
* Optional configuration to override default scroll behavior.
|
|
42
|
-
*/
|
|
43
|
-
options?: SmoothScrollOptions;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* StateEffect for triggering smooth scroll to a specific line.
|
|
48
|
-
*/
|
|
49
|
-
export const scrollToLineEffect = StateEffect.define<ScrollToLineProps>();
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Extension that provides smooth scrolling to specific lines in the editor.
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* ```typescript
|
|
56
|
-
* // Add to editor extensions.
|
|
57
|
-
* const extensions = [
|
|
58
|
-
* smoothScroll()
|
|
59
|
-
* ];
|
|
60
|
-
*
|
|
61
|
-
* // Trigger scroll to line 42.
|
|
62
|
-
* view.dispatch({
|
|
63
|
-
* effects: scrollToLineEffect.of({ line: 42 })
|
|
64
|
-
* });
|
|
65
|
-
*
|
|
66
|
-
* // Scroll with custom options.
|
|
67
|
-
* view.dispatch({
|
|
68
|
-
* effects: scrollToLineEffect.of({ line: 100, options: { offset: -50 } })
|
|
69
|
-
* });
|
|
70
|
-
*
|
|
71
|
-
* // Scroll so line appears at end (bottom) of screen.
|
|
72
|
-
* view.dispatch({
|
|
73
|
-
* effects: scrollToLineEffect.of({ line: 50, options: { position: 'end' } })
|
|
74
|
-
* });
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export const smoothScroll = ({ offset = 0, position = 'start' }: Partial<SmoothScrollOptions> = {}) => {
|
|
78
|
-
// ViewPlugin to manage scroll animations.
|
|
79
|
-
const scrollPlugin = ViewPlugin.fromClass(
|
|
80
|
-
class SmoothScrollPlugin {
|
|
81
|
-
constructor(private readonly view: EditorView) {}
|
|
82
|
-
|
|
83
|
-
// No-op.
|
|
84
|
-
destroy() {}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Perform smooth scroll to the specified line.
|
|
88
|
-
*/
|
|
89
|
-
scrollToLine(lineNumber: number, options: SmoothScrollOptions) {
|
|
90
|
-
const { offset: animOffset = 0, position: animPosition, behavior } = options;
|
|
91
|
-
const doc = this.view.state.doc;
|
|
92
|
-
const scroller = this.view.scrollDOM;
|
|
93
|
-
|
|
94
|
-
// Convert 1-based line number to 0-based.
|
|
95
|
-
const targetLine = Math.max(0, lineNumber - 1);
|
|
96
|
-
if (behavior === 'instant') {
|
|
97
|
-
requestAnimationFrame(() => {
|
|
98
|
-
this.view.dispatch({
|
|
99
|
-
selection: { anchor: doc.line(targetLine + 1).from },
|
|
100
|
-
scrollIntoView: true,
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Get the position of the target line.
|
|
107
|
-
if (targetLine >= doc.lines) {
|
|
108
|
-
// Line doesn't exist, scroll to end.
|
|
109
|
-
const targetScrollTop = scroller.scrollHeight - scroller.clientHeight + (animOffset || 0);
|
|
110
|
-
this.animateScroll(scroller, targetScrollTop);
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const lineStart = doc.line(targetLine + 1).from;
|
|
115
|
-
const coords = this.view.coordsAtPos(lineStart);
|
|
116
|
-
if (!coords) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Calculate target scroll position based on position option.
|
|
121
|
-
const currentScrollTop = scroller.scrollTop;
|
|
122
|
-
const scrollerRect = scroller.getBoundingClientRect();
|
|
123
|
-
const maxScrollTop = scroller.scrollHeight - scroller.clientHeight;
|
|
124
|
-
|
|
125
|
-
let targetScrollTop: number;
|
|
126
|
-
if (animPosition === 'end') {
|
|
127
|
-
// Position line at end (bottom) of viewport.
|
|
128
|
-
// Calculate how far down we need to scroll so the line's bottom aligns with viewport bottom.
|
|
129
|
-
targetScrollTop = currentScrollTop + coords.bottom - scrollerRect.bottom + animOffset;
|
|
130
|
-
} else {
|
|
131
|
-
// Default: position line at start (top) of viewport.
|
|
132
|
-
targetScrollTop = currentScrollTop + coords.top - scrollerRect.top + animOffset;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Clamp to valid scroll range.
|
|
136
|
-
const clampedScrollTop = Math.max(0, Math.min(targetScrollTop, maxScrollTop));
|
|
137
|
-
this.animateScroll(scroller, clampedScrollTop);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Animate scroll using browser's built-in smooth scrolling.
|
|
142
|
-
*/
|
|
143
|
-
private animateScroll(element: HTMLElement, targetScrollTop: number) {
|
|
144
|
-
if (Math.abs(targetScrollTop - element.scrollTop) < 1) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Use browser's built-in smooth scrolling.
|
|
149
|
-
element.scrollTo({
|
|
150
|
-
top: targetScrollTop,
|
|
151
|
-
behavior: 'smooth',
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
},
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
return [
|
|
158
|
-
scrollPlugin,
|
|
159
|
-
|
|
160
|
-
// Update listener to handle scroll effects.
|
|
161
|
-
EditorView.updateListener.of((update) => {
|
|
162
|
-
update.transactions.forEach((transaction) => {
|
|
163
|
-
for (const effect of transaction.effects) {
|
|
164
|
-
if (effect.is(scrollToLineEffect)) {
|
|
165
|
-
const { line, options = {} } = effect.value;
|
|
166
|
-
const plugin = update.view.plugin(scrollPlugin);
|
|
167
|
-
if (plugin) {
|
|
168
|
-
plugin.scrollToLine(line, { offset, position, ...options });
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
}),
|
|
174
|
-
];
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Helper function to scroll to a specific line.
|
|
179
|
-
* This is a convenience function that can be used directly with an EditorView.
|
|
180
|
-
*
|
|
181
|
-
* @param view - The CodeMirror EditorView instance
|
|
182
|
-
* @param line - The line number to scroll to (1-based)
|
|
183
|
-
* @param options - Optional scroll configuration
|
|
184
|
-
*/
|
|
185
|
-
export const scrollToLine = (view: EditorView, line: number, options?: SmoothScrollOptions) => {
|
|
186
|
-
view.dispatch({
|
|
187
|
-
effects: scrollToLineEffect.of({ line, options }),
|
|
188
|
-
});
|
|
189
|
-
};
|
package/src/styles/markdown.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { mx } from '@dxos/ui-theme';
|
|
6
|
-
|
|
7
|
-
export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
8
|
-
|
|
9
|
-
// https://tailwindcss.com/docs/font-weight
|
|
10
|
-
const headings: Record<HeadingLevel, string> = {
|
|
11
|
-
1: 'text-4xl',
|
|
12
|
-
2: 'text-3xl',
|
|
13
|
-
3: 'text-2xl',
|
|
14
|
-
4: 'text-xl',
|
|
15
|
-
5: 'text-lg',
|
|
16
|
-
6: '', // TODO(burdon): Should be text-base, but that's a color in our system.
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const markdownTheme = {
|
|
20
|
-
code: 'font-mono !no-underline text-neutral-700 dark:text-neutral-300',
|
|
21
|
-
codeMark: 'font-mono text-primary-500',
|
|
22
|
-
mark: 'opacity-50',
|
|
23
|
-
heading: (level: HeadingLevel) => {
|
|
24
|
-
return mx(headings[level], 'dark:text-neutral-400');
|
|
25
|
-
},
|
|
26
|
-
};
|
package/src/styles/tokens.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { tokens } from '@dxos/ui-theme';
|
|
6
|
-
import { get } from '@dxos/util';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Returns the tailwind token value.
|
|
10
|
-
*/
|
|
11
|
-
const getToken = (path: string, defaultValue?: string | string[]): string => {
|
|
12
|
-
const value = get(tokens, path, defaultValue);
|
|
13
|
-
return value?.toString() ?? '';
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const fontBody = getToken('fontFamily.body');
|
|
17
|
-
export const fontMono = getToken('fontFamily.mono');
|