@dxos/react-ui-editor 0.6.8-main.3be982f → 0.6.8-staging.63bcb81
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 +535 -521
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/TextEditor.stories.d.ts +5 -2
- package/dist/types/src/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/defaults.d.ts +2 -2
- package/dist/types/src/defaults.d.ts.map +1 -1
- package/dist/types/src/extensions/doc.d.ts +3 -0
- package/dist/types/src/extensions/doc.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/folding.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts +2 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link-paste.d.ts +3 -0
- package/dist/types/src/extensions/markdown/link-paste.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts +3 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/dist/types/src/extensions/state.d.ts +14 -14
- package/dist/types/src/extensions/state.d.ts.map +1 -1
- package/dist/types/src/extensions/util/react.d.ts +1 -1
- package/dist/types/src/extensions/util/react.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts +5 -3
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts +7 -17
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/styles/theme.d.ts +3 -1
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/styles/tokens.d.ts +5 -7
- package/dist/types/src/styles/tokens.d.ts.map +1 -1
- package/package.json +24 -24
- package/src/TextEditor.stories.tsx +40 -27
- package/src/defaults.ts +9 -2
- package/src/extensions/doc.ts +3 -0
- package/src/extensions/factories.ts +3 -2
- package/src/extensions/folding.tsx +5 -7
- package/src/extensions/markdown/bundle.ts +1 -3
- package/src/extensions/markdown/decorate.ts +31 -24
- package/src/extensions/markdown/formatting.ts +3 -1
- package/src/extensions/markdown/highlight.ts +33 -19
- package/src/extensions/markdown/link-paste.ts +3 -0
- package/src/extensions/state.ts +41 -35
- package/src/extensions/util/react.tsx +3 -4
- package/src/hooks/useTextEditor.ts +24 -29
- package/src/index.ts +2 -0
- package/src/styles/markdown.ts +17 -40
- package/src/styles/theme.ts +91 -86
- package/src/styles/tokens.ts +9 -7
|
@@ -7,7 +7,7 @@ import { HighlightStyle } from '@codemirror/language';
|
|
|
7
7
|
import { tags, styleTags, Tag } from '@lezer/highlight';
|
|
8
8
|
import { type MarkdownConfig, Table } from '@lezer/markdown';
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { getToken, theme } from '../../styles';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Custom tags defined and processed by the GFM lezer extension.
|
|
@@ -49,6 +49,8 @@ export const markdownTagsExtensions: MarkdownConfig[] = [
|
|
|
49
49
|
},
|
|
50
50
|
];
|
|
51
51
|
|
|
52
|
+
export type HighlightOptions = {};
|
|
53
|
+
|
|
52
54
|
/**
|
|
53
55
|
* Styling based on `lezer` parser tags.
|
|
54
56
|
* https://codemirror.net/examples/styling
|
|
@@ -60,7 +62,7 @@ export const markdownTagsExtensions: MarkdownConfig[] = [
|
|
|
60
62
|
* - https://github.com/codemirror/language/blob/main/src/highlight.ts#L194
|
|
61
63
|
* - https://github.com/codemirror/theme-one-dark/blob/main/src/one-dark.ts#L115
|
|
62
64
|
*/
|
|
63
|
-
export const markdownHighlightStyle = (
|
|
65
|
+
export const markdownHighlightStyle = (_options: HighlightOptions = {}) => {
|
|
64
66
|
return HighlightStyle.define(
|
|
65
67
|
[
|
|
66
68
|
{
|
|
@@ -99,6 +101,7 @@ export const markdownHighlightStyle = (readonly?: boolean) => {
|
|
|
99
101
|
tags.inserted,
|
|
100
102
|
tags.invalid,
|
|
101
103
|
],
|
|
104
|
+
// TODO(burdon): Explain.
|
|
102
105
|
color: 'inherit !important',
|
|
103
106
|
},
|
|
104
107
|
|
|
@@ -111,38 +114,49 @@ export const markdownHighlightStyle = (readonly?: boolean) => {
|
|
|
111
114
|
markdownTags.LinkReference,
|
|
112
115
|
markdownTags.ListMark,
|
|
113
116
|
],
|
|
114
|
-
class: mark,
|
|
117
|
+
class: theme.mark,
|
|
115
118
|
},
|
|
116
119
|
|
|
117
120
|
// Markdown marks.
|
|
118
121
|
{
|
|
119
|
-
tag: [
|
|
120
|
-
|
|
122
|
+
tag: [
|
|
123
|
+
//
|
|
124
|
+
markdownTags.CodeMark,
|
|
125
|
+
markdownTags.HeaderMark,
|
|
126
|
+
markdownTags.QuoteMark,
|
|
127
|
+
markdownTags.EmphasisMark,
|
|
128
|
+
],
|
|
129
|
+
class: theme.mark,
|
|
121
130
|
},
|
|
122
131
|
|
|
123
132
|
// E.g., code block language (after ```).
|
|
124
133
|
{
|
|
125
|
-
tag: [
|
|
126
|
-
|
|
134
|
+
tag: [
|
|
135
|
+
//
|
|
136
|
+
tags.function(tags.variableName),
|
|
137
|
+
tags.labelName,
|
|
138
|
+
],
|
|
139
|
+
class: theme.codeMark,
|
|
127
140
|
},
|
|
128
141
|
|
|
142
|
+
// Fonts.
|
|
129
143
|
{
|
|
130
144
|
tag: [tags.monospace],
|
|
131
145
|
class: 'font-mono',
|
|
132
146
|
},
|
|
133
147
|
|
|
134
148
|
// Headings.
|
|
135
|
-
{ tag: tags.heading1, class: heading(1) },
|
|
136
|
-
{ tag: tags.heading2, class: heading(2) },
|
|
137
|
-
{ tag: tags.heading3, class: heading(3) },
|
|
138
|
-
{ tag: tags.heading4, class: heading(4) },
|
|
139
|
-
{ tag: tags.heading5, class: heading(5) },
|
|
140
|
-
{ tag: tags.heading6, class: heading(6) },
|
|
149
|
+
{ tag: tags.heading1, class: theme.heading(1) },
|
|
150
|
+
{ tag: tags.heading2, class: theme.heading(2) },
|
|
151
|
+
{ tag: tags.heading3, class: theme.heading(3) },
|
|
152
|
+
{ tag: tags.heading4, class: theme.heading(4) },
|
|
153
|
+
{ tag: tags.heading5, class: theme.heading(5) },
|
|
154
|
+
{ tag: tags.heading6, class: theme.heading(6) },
|
|
141
155
|
|
|
142
156
|
// Emphasis.
|
|
143
|
-
{ tag: tags.emphasis, class: italic },
|
|
144
|
-
{ tag: tags.strong, class: bold },
|
|
145
|
-
{ tag: tags.strikethrough, class:
|
|
157
|
+
{ tag: tags.emphasis, class: 'italic' },
|
|
158
|
+
{ tag: tags.strong, class: 'font-bold' },
|
|
159
|
+
{ tag: tags.strikethrough, class: 'line-through' },
|
|
146
160
|
|
|
147
161
|
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
148
162
|
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
@@ -151,12 +165,12 @@ export const markdownHighlightStyle = (readonly?: boolean) => {
|
|
|
151
165
|
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
152
166
|
{
|
|
153
167
|
tag: [markdownTags.CodeText, markdownTags.InlineCode],
|
|
154
|
-
class: code,
|
|
168
|
+
class: theme.code,
|
|
155
169
|
},
|
|
156
170
|
|
|
157
171
|
{
|
|
158
172
|
tag: [markdownTags.QuoteMark],
|
|
159
|
-
class: blockquote,
|
|
173
|
+
class: theme.blockquote,
|
|
160
174
|
},
|
|
161
175
|
|
|
162
176
|
{
|
|
@@ -167,7 +181,7 @@ export const markdownHighlightStyle = (readonly?: boolean) => {
|
|
|
167
181
|
{
|
|
168
182
|
scope: markdownLanguage,
|
|
169
183
|
all: {
|
|
170
|
-
fontFamily: getToken('fontFamily.body'
|
|
184
|
+
fontFamily: getToken('fontFamily.body'),
|
|
171
185
|
},
|
|
172
186
|
},
|
|
173
187
|
);
|
|
@@ -7,6 +7,9 @@ import { type EditorState, Transaction } from '@codemirror/state';
|
|
|
7
7
|
import { ViewPlugin, type ViewUpdate, type PluginValue } from '@codemirror/view';
|
|
8
8
|
import { type SyntaxNode } from '@lezer/common';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Formats pasted URLs as markdown links and images.
|
|
12
|
+
*/
|
|
10
13
|
export const linkPastePlugin = ViewPlugin.fromClass(
|
|
11
14
|
class implements PluginValue {
|
|
12
15
|
update(update: ViewUpdate) {
|
package/src/extensions/state.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type Extension, Transaction } from '@codemirror/state';
|
|
5
|
+
import { type Extension, Transaction, type TransactionSpec } from '@codemirror/state';
|
|
6
6
|
import { EditorView, keymap } from '@codemirror/view';
|
|
7
7
|
|
|
8
8
|
import { debounce } from '@dxos/async';
|
|
@@ -11,76 +11,82 @@ import { isNotFalsy } from '@dxos/util';
|
|
|
11
11
|
|
|
12
12
|
import { documentId } from './doc';
|
|
13
13
|
|
|
14
|
-
const
|
|
14
|
+
const stateRestoreAnnotation = 'dxos.org/cm/state-restore';
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
16
|
+
export type EditorSelection = {
|
|
17
|
+
anchor: number;
|
|
18
|
+
head?: number;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type EditorSelectionState = {
|
|
22
|
+
scrollTo?: number;
|
|
23
|
+
selection?: EditorSelection;
|
|
25
24
|
};
|
|
26
25
|
|
|
27
|
-
export type
|
|
28
|
-
setState: (id: string, state:
|
|
29
|
-
getState: (id: string) =>
|
|
26
|
+
export type EditorStateOptions = {
|
|
27
|
+
setState: (id: string, state: EditorSelectionState) => void;
|
|
28
|
+
getState: (id: string) => EditorSelectionState | undefined;
|
|
30
29
|
};
|
|
31
30
|
|
|
32
31
|
const keyPrefix = 'dxos.org/react-ui-editor/state';
|
|
33
|
-
export const localStorageStateStoreAdapter:
|
|
34
|
-
setState: (id, state) => {
|
|
35
|
-
invariant(id);
|
|
36
|
-
localStorage.setItem(`${keyPrefix}/${id}`, JSON.stringify(state));
|
|
37
|
-
},
|
|
32
|
+
export const localStorageStateStoreAdapter: EditorStateOptions = {
|
|
38
33
|
getState: (id) => {
|
|
39
34
|
invariant(id);
|
|
40
35
|
const state = localStorage.getItem(`${keyPrefix}/${id}`);
|
|
41
36
|
return state ? JSON.parse(state) : undefined;
|
|
42
37
|
},
|
|
38
|
+
|
|
39
|
+
setState: (id, state) => {
|
|
40
|
+
invariant(id);
|
|
41
|
+
localStorage.setItem(`${keyPrefix}/${id}`, JSON.stringify(state));
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const createEditorStateTransaction = ({ scrollTo, selection }: EditorSelectionState): TransactionSpec => {
|
|
46
|
+
return {
|
|
47
|
+
selection,
|
|
48
|
+
scrollIntoView: !scrollTo,
|
|
49
|
+
effects: scrollTo ? EditorView.scrollIntoView(scrollTo, { yMargin: 96 }) : undefined,
|
|
50
|
+
annotations: Transaction.userEvent.of(stateRestoreAnnotation),
|
|
51
|
+
};
|
|
43
52
|
};
|
|
44
53
|
|
|
45
54
|
/**
|
|
46
55
|
* Track scrolling and selection state to be restored when switching to document.
|
|
47
56
|
*/
|
|
48
|
-
export const state = ({ getState, setState }: Partial<
|
|
57
|
+
export const state = ({ getState, setState }: Partial<EditorStateOptions> = {}): Extension => {
|
|
49
58
|
const setStateDebounced = debounce(setState!, 1_000);
|
|
50
59
|
|
|
51
60
|
return [
|
|
52
61
|
// TODO(burdon): Track scrolling (currently only updates when cursor moves).
|
|
53
|
-
EditorView.
|
|
54
|
-
|
|
62
|
+
// EditorView.domEventHandlers({
|
|
63
|
+
// scroll: (event) => {
|
|
64
|
+
// setStateDebounced(id, {});
|
|
65
|
+
// },
|
|
66
|
+
// }),
|
|
67
|
+
EditorView.updateListener.of(({ view, transactions }) => {
|
|
55
68
|
const id = view.state.facet(documentId);
|
|
56
|
-
if (!id || transactions.some((tr) => tr.isUserEvent(
|
|
69
|
+
if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
|
|
57
70
|
return;
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
if (setState) {
|
|
61
|
-
const {
|
|
62
|
-
const pos = view.posAtCoords({ x: 0, y:
|
|
74
|
+
const { scrollTop } = view.scrollDOM;
|
|
75
|
+
const pos = view.posAtCoords({ x: 0, y: scrollTop });
|
|
63
76
|
if (pos !== null) {
|
|
64
77
|
const { anchor, head } = view.state.selection.main;
|
|
65
|
-
setStateDebounced(id, {
|
|
66
|
-
scrollTo: { from: pos, yMargin: 0 },
|
|
67
|
-
selection: { anchor, head },
|
|
68
|
-
});
|
|
78
|
+
setStateDebounced(id, { scrollTo: pos, selection: { anchor, head } });
|
|
69
79
|
}
|
|
70
80
|
}
|
|
71
81
|
}),
|
|
72
82
|
getState &&
|
|
73
83
|
keymap.of([
|
|
74
84
|
{
|
|
75
|
-
key: 'ctrl-r', // TODO(burdon): Setting to jump back to
|
|
85
|
+
key: 'ctrl-r', // TODO(burdon): Setting to jump back to selection.
|
|
76
86
|
run: (view) => {
|
|
77
87
|
const state = getState(view.state.facet(documentId));
|
|
78
88
|
if (state) {
|
|
79
|
-
view.dispatch(
|
|
80
|
-
effects: EditorView.scrollIntoView(state.scrollTo.from, { yMargin: 0 }),
|
|
81
|
-
selection: state.selection,
|
|
82
|
-
annotations: Transaction.userEvent.of(scrollAnnotation),
|
|
83
|
-
});
|
|
89
|
+
view.dispatch(createEditorStateTransaction(state));
|
|
84
90
|
}
|
|
85
91
|
return true;
|
|
86
92
|
},
|
|
@@ -8,8 +8,7 @@ import { createRoot } from 'react-dom/client';
|
|
|
8
8
|
import { ThemeProvider } from '@dxos/react-ui';
|
|
9
9
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
10
10
|
|
|
11
|
-
export const renderRoot = (node: ReactNode) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return el;
|
|
11
|
+
export const renderRoot = (root: HTMLElement, node: ReactNode): HTMLElement => {
|
|
12
|
+
createRoot(root).render(<ThemeProvider tx={defaultTx}>{node}</ThemeProvider>);
|
|
13
|
+
return root;
|
|
15
14
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { EditorState, type EditorStateConfig
|
|
5
|
+
import { EditorState, type EditorStateConfig } from '@codemirror/state';
|
|
6
6
|
import { EditorView } from '@codemirror/view';
|
|
7
7
|
import { useFocusableGroup } from '@fluentui/react-tabster';
|
|
8
8
|
import {
|
|
@@ -17,10 +17,9 @@ import {
|
|
|
17
17
|
} from 'react';
|
|
18
18
|
|
|
19
19
|
import { log } from '@dxos/log';
|
|
20
|
-
import { useDefaultValue } from '@dxos/react-ui';
|
|
21
20
|
import { isNotFalsy, type MaybeFunction } from '@dxos/util';
|
|
22
21
|
|
|
23
|
-
import { documentId, editorInputMode } from '../extensions';
|
|
22
|
+
import { createEditorStateTransaction, documentId, editorInputMode, type EditorSelection } from '../extensions';
|
|
24
23
|
import { logChanges } from '../util';
|
|
25
24
|
|
|
26
25
|
export type UseTextEditor = {
|
|
@@ -41,12 +40,13 @@ export type CursorInfo = {
|
|
|
41
40
|
after?: string;
|
|
42
41
|
};
|
|
43
42
|
|
|
44
|
-
export type UseTextEditorProps = Pick<EditorStateConfig, '
|
|
43
|
+
export type UseTextEditorProps = Pick<EditorStateConfig, 'extensions'> & {
|
|
45
44
|
id?: string;
|
|
46
45
|
initialValue?: string;
|
|
47
46
|
className?: string;
|
|
48
47
|
autoFocus?: boolean;
|
|
49
|
-
scrollTo?:
|
|
48
|
+
scrollTo?: number;
|
|
49
|
+
selection?: EditorSelection;
|
|
50
50
|
moveToEndOfLine?: boolean;
|
|
51
51
|
debug?: boolean;
|
|
52
52
|
};
|
|
@@ -60,22 +60,14 @@ export const useTextEditor = (
|
|
|
60
60
|
props: MaybeFunction<UseTextEditorProps> = {},
|
|
61
61
|
deps: DependencyList = [],
|
|
62
62
|
): UseTextEditor => {
|
|
63
|
-
const {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
extensions,
|
|
68
|
-
autoFocus,
|
|
69
|
-
scrollTo: _scrollTo,
|
|
70
|
-
moveToEndOfLine,
|
|
71
|
-
debug,
|
|
72
|
-
} = useMemo<UseTextEditorProps>(() => {
|
|
73
|
-
return typeof props === 'function' ? props() : props;
|
|
74
|
-
}, deps ?? []);
|
|
63
|
+
const { id, initialValue, extensions, autoFocus, scrollTo, selection, moveToEndOfLine, debug } =
|
|
64
|
+
useMemo<UseTextEditorProps>(() => {
|
|
65
|
+
return typeof props === 'function' ? props() : props;
|
|
66
|
+
}, deps ?? []);
|
|
75
67
|
|
|
76
68
|
// NOTE: Increments by 2 in strict mode.
|
|
77
69
|
const [instanceId] = useState(() => `text-editor-${++instanceCount}`);
|
|
78
|
-
|
|
70
|
+
// Callback once view is created.
|
|
79
71
|
const onUpdate = useRef<() => void>();
|
|
80
72
|
const [view, setView] = useState<EditorView>();
|
|
81
73
|
const parentRef = useRef<HTMLDivElement>(null);
|
|
@@ -85,8 +77,12 @@ export const useTextEditor = (
|
|
|
85
77
|
if (parentRef.current) {
|
|
86
78
|
log('create', { id, instanceId, doc: initialValue?.length ?? 0 });
|
|
87
79
|
|
|
88
|
-
let initialSelection
|
|
89
|
-
if (
|
|
80
|
+
let initialSelection;
|
|
81
|
+
if (selection?.anchor && initialValue?.length) {
|
|
82
|
+
if (selection.anchor <= initialValue.length && (selection?.head ?? 0) <= initialValue.length) {
|
|
83
|
+
initialSelection = selection;
|
|
84
|
+
}
|
|
85
|
+
} else if (moveToEndOfLine && selection === undefined) {
|
|
90
86
|
const index = initialValue?.indexOf('\n');
|
|
91
87
|
const anchor = !index || index === -1 ? 0 : index;
|
|
92
88
|
initialSelection = { anchor };
|
|
@@ -105,7 +101,9 @@ export const useTextEditor = (
|
|
|
105
101
|
}),
|
|
106
102
|
extensions,
|
|
107
103
|
EditorView.updateListener.of(() => {
|
|
108
|
-
|
|
104
|
+
setTimeout(() => {
|
|
105
|
+
onUpdate.current?.();
|
|
106
|
+
});
|
|
109
107
|
}),
|
|
110
108
|
].filter(isNotFalsy),
|
|
111
109
|
});
|
|
@@ -113,7 +111,6 @@ export const useTextEditor = (
|
|
|
113
111
|
// https://codemirror.net/docs/ref/#view.EditorViewConfig
|
|
114
112
|
view = new EditorView({
|
|
115
113
|
parent: parentRef.current,
|
|
116
|
-
scrollTo,
|
|
117
114
|
selection: initialSelection,
|
|
118
115
|
state,
|
|
119
116
|
// NOTE: Uncomment to debug/monitor all transactions.
|
|
@@ -143,13 +140,11 @@ export const useTextEditor = (
|
|
|
143
140
|
|
|
144
141
|
useEffect(() => {
|
|
145
142
|
if (view) {
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
onUpdate.current =
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
};
|
|
152
|
-
}
|
|
143
|
+
// NOTE: Set selection after first update (since content may rerender on focus).
|
|
144
|
+
onUpdate.current = () => {
|
|
145
|
+
onUpdate.current = undefined;
|
|
146
|
+
view.dispatch(createEditorStateTransaction({ scrollTo, selection }));
|
|
147
|
+
};
|
|
153
148
|
|
|
154
149
|
// Remove tabster attribute (rely on custom keymap).
|
|
155
150
|
if (view.state.facet(editorInputMode).noTabster) {
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,8 @@ export { tags } from '@lezer/highlight';
|
|
|
10
10
|
|
|
11
11
|
export { TextKind } from '@dxos/protocols/proto/dxos/echo/model/text';
|
|
12
12
|
|
|
13
|
+
export { getToken } from './styles';
|
|
14
|
+
|
|
13
15
|
export * from './components';
|
|
14
16
|
export * from './defaults';
|
|
15
17
|
export * from './extensions';
|
package/src/styles/markdown.ts
CHANGED
|
@@ -6,48 +6,25 @@ import { mx } from '@dxos/react-ui-theme';
|
|
|
6
6
|
|
|
7
7
|
export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
8
8
|
|
|
9
|
-
// TODO(burdon): Better way to align vertically than negative margin? Font-specific?
|
|
10
9
|
// https://tailwindcss.com/docs/font-weight
|
|
11
10
|
const headings: Record<HeadingLevel, string> = {
|
|
12
|
-
1: '
|
|
13
|
-
2: '
|
|
14
|
-
3: '
|
|
15
|
-
4: '
|
|
16
|
-
5: '
|
|
17
|
-
6: '
|
|
11
|
+
1: 'text-4xl',
|
|
12
|
+
2: 'text-3xl',
|
|
13
|
+
3: 'text-2xl',
|
|
14
|
+
4: 'text-xl',
|
|
15
|
+
5: 'text-lg',
|
|
16
|
+
6: 'text-md',
|
|
18
17
|
};
|
|
19
18
|
|
|
20
|
-
// TODO(burdon):
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
// TODO(burdon): Define theme as facet (used in multiple extensions).
|
|
20
|
+
// TODO(burdon): Organize theme styles for widgets.
|
|
21
|
+
export const theme = {
|
|
22
|
+
mark: 'opacity-50',
|
|
23
|
+
code: 'font-mono !no-underline text-neutral-700 dark:text-neutral-300',
|
|
24
|
+
codeMark: 'font-mono text-primary-500',
|
|
25
|
+
// TODO(burdon): Replace with widget.
|
|
26
|
+
blockquote: 'pl-1 mr-1 border-is-4 border-orange-500 dark:border-orange-500 dark:text-neutral-500',
|
|
27
|
+
heading: (level: HeadingLevel) => {
|
|
28
|
+
return mx(headings[level], 'dark:text-primary-400');
|
|
29
|
+
},
|
|
23
30
|
};
|
|
24
|
-
|
|
25
|
-
export const text = 'text-neutral-800 dark:text-neutral-200';
|
|
26
|
-
export const light = 'text-neutral-200 dark:text-neutral-800';
|
|
27
|
-
|
|
28
|
-
export const mark = mx('!font-normal !no-underline !text-inherit opacity-40', light);
|
|
29
|
-
|
|
30
|
-
export const paragraph = 'mlb-1';
|
|
31
|
-
|
|
32
|
-
export const bold = 'font-bold';
|
|
33
|
-
export const italic = 'italic';
|
|
34
|
-
export const strikethrough = 'line-through';
|
|
35
|
-
|
|
36
|
-
export const code = 'font-mono !no-underline text-neutral-700 dark:text-neutral-300';
|
|
37
|
-
export const codeMark = 'font-mono text-primary-500';
|
|
38
|
-
export const codeBlock = 'mlb-2 font-mono bg-neutral-500/10 p-3 rounded';
|
|
39
|
-
|
|
40
|
-
export const inlineUrl = mx(code, 'px-1');
|
|
41
|
-
|
|
42
|
-
export const blockquote = mx('pl-1 mr-1 border-is-4 border-orange-500 dark:border-orange-500 text-transparent');
|
|
43
|
-
|
|
44
|
-
export const horizontalRule =
|
|
45
|
-
'flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-200 dark:border-neutral-800';
|
|
46
|
-
|
|
47
|
-
// TODO(thure): Tailwind was not seeing `[&>li:before]:content-["•"]` as a utility class, but it would work if instead of `"•"` it was `"X"`… why?
|
|
48
|
-
export const unorderedList =
|
|
49
|
-
'mlb-2 grid grid-cols-[min-content_1fr] [&>li:before]:content-[attr(marker)] [&>li:before]:mlb-1 [&>li:before]:mie-2';
|
|
50
|
-
export const orderedList =
|
|
51
|
-
'mlb-2 grid grid-cols-[min-content_1fr] [&>li:before]:content-[counters(section,_".")_"._"] [counter-reset:section] [&>li:before]:mlb-1';
|
|
52
|
-
|
|
53
|
-
export const listItem = 'contents before:[counter-increment:section]';
|