@dxos/react-ui-editor 0.6.8-main.046e6cf → 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.
Files changed (53) hide show
  1. package/dist/lib/browser/index.mjs +535 -521
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/TextEditor.stories.d.ts +5 -2
  5. package/dist/types/src/TextEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/defaults.d.ts +2 -2
  7. package/dist/types/src/defaults.d.ts.map +1 -1
  8. package/dist/types/src/extensions/doc.d.ts +3 -0
  9. package/dist/types/src/extensions/doc.d.ts.map +1 -1
  10. package/dist/types/src/extensions/factories.d.ts.map +1 -1
  11. package/dist/types/src/extensions/folding.d.ts.map +1 -1
  12. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  13. package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
  14. package/dist/types/src/extensions/markdown/formatting.d.ts +1 -1
  15. package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
  16. package/dist/types/src/extensions/markdown/highlight.d.ts +2 -1
  17. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  18. package/dist/types/src/extensions/markdown/link-paste.d.ts +3 -0
  19. package/dist/types/src/extensions/markdown/link-paste.d.ts.map +1 -1
  20. package/dist/types/src/extensions/markdown/link.d.ts +3 -1
  21. package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
  22. package/dist/types/src/extensions/state.d.ts +14 -14
  23. package/dist/types/src/extensions/state.d.ts.map +1 -1
  24. package/dist/types/src/extensions/util/react.d.ts +1 -1
  25. package/dist/types/src/extensions/util/react.d.ts.map +1 -1
  26. package/dist/types/src/hooks/useTextEditor.d.ts +5 -3
  27. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
  28. package/dist/types/src/index.d.ts +1 -0
  29. package/dist/types/src/index.d.ts.map +1 -1
  30. package/dist/types/src/styles/markdown.d.ts +7 -17
  31. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  32. package/dist/types/src/styles/theme.d.ts +3 -1
  33. package/dist/types/src/styles/theme.d.ts.map +1 -1
  34. package/dist/types/src/styles/tokens.d.ts +5 -7
  35. package/dist/types/src/styles/tokens.d.ts.map +1 -1
  36. package/package.json +24 -24
  37. package/src/TextEditor.stories.tsx +40 -27
  38. package/src/defaults.ts +9 -2
  39. package/src/extensions/doc.ts +3 -0
  40. package/src/extensions/factories.ts +3 -2
  41. package/src/extensions/folding.tsx +5 -7
  42. package/src/extensions/markdown/bundle.ts +1 -3
  43. package/src/extensions/markdown/decorate.ts +31 -24
  44. package/src/extensions/markdown/formatting.ts +3 -1
  45. package/src/extensions/markdown/highlight.ts +33 -19
  46. package/src/extensions/markdown/link-paste.ts +3 -0
  47. package/src/extensions/state.ts +41 -35
  48. package/src/extensions/util/react.tsx +3 -4
  49. package/src/hooks/useTextEditor.ts +24 -29
  50. package/src/index.ts +2 -0
  51. package/src/styles/markdown.ts +17 -40
  52. package/src/styles/theme.ts +91 -86
  53. package/src/styles/tokens.ts +9 -7
@@ -2,10 +2,13 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import get from 'lodash.get';
5
+ import { type StyleSpec } from 'style-mod';
6
6
 
7
- import { type ThemeStyles, tokens } from './tokens';
7
+ import { getToken } from './tokens';
8
8
 
9
+ export type ThemeStyles = Record<string, StyleSpec>;
10
+
11
+ // TODO(burdon): Factor out theme.
9
12
  // TODO(burdon): Can we use @apply and import css file?
10
13
  // https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply?
11
14
 
@@ -19,6 +22,7 @@ import { type ThemeStyles, tokens } from './tokens';
19
22
  *
20
23
  * Main layout:
21
24
  * https://codemirror.net/examples/styling
25
+ * https://codemirror.net/docs/guide (DOM Structure).
22
26
  *
23
27
  * <div class="cm-editor [cm-focused] [generated classes]">
24
28
  * <div class="cm-scroller">
@@ -48,25 +52,41 @@ export const defaultTheme: ThemeStyles = {
48
52
  outline: 'none',
49
53
  },
50
54
 
51
- // Scroller.
52
- // NOTE: See https://codemirror.net/docs/guide (DOM Structure).
55
+ /**
56
+ * Scroller
57
+ */
53
58
  '.cm-scroller': {
54
59
  overflowY: 'auto',
55
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
56
- lineHeight: 1.5,
57
60
  },
58
61
 
59
- // Content.
62
+ /**
63
+ * Content
64
+ * NOTE: Apply margins to content so that scrollbar is at the edge of the container.
65
+ */
60
66
  '.cm-content': {
61
67
  padding: 'unset',
62
68
  // NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
63
69
  fontSize: '16px',
70
+ fontFamily: getToken('fontFamily.body'),
71
+ lineHeight: 1.5,
64
72
  },
65
73
  '&light .cm-content': {
66
- color: get(tokens, 'extend.semanticColors.base.fg.light', 'black'),
74
+ color: getToken('extend.semanticColors.base.fg.light', 'black'),
67
75
  },
68
76
  '&dark .cm-content': {
69
- color: get(tokens, 'extend.semanticColors.base.fg.dark', 'red'),
77
+ color: getToken('extend.semanticColors.base.fg.dark', 'white'),
78
+ },
79
+
80
+ /**
81
+ * Gutters
82
+ * NOTE: Gutters should have the same top margin as the content.
83
+ */
84
+ '.cm-gutters': {
85
+ background: 'transparent',
86
+ },
87
+ '.cm-gutter': {},
88
+ '.cm-gutterElement': {
89
+ lineHeight: 1.5,
70
90
  },
71
91
 
72
92
  //
@@ -79,10 +99,10 @@ export const defaultTheme: ThemeStyles = {
79
99
  borderLeft: '2px solid white',
80
100
  },
81
101
  '&light .cm-placeholder': {
82
- color: get(tokens, 'extend.semanticColors.description.light', 'rgba(0,0,0,.2)'),
102
+ color: getToken('extend.semanticColors.description.light', 'rgba(0,0,0,.2)'),
83
103
  },
84
104
  '&dark .cm-placeholder': {
85
- color: get(tokens, 'extend.semanticColors.description.dark', 'rgba(255,255,255,.2)'),
105
+ color: getToken('extend.semanticColors.description.dark', 'rgba(255,255,255,.2)'),
86
106
  },
87
107
 
88
108
  //
@@ -107,16 +127,16 @@ export const defaultTheme: ThemeStyles = {
107
127
  //
108
128
 
109
129
  '&light .cm-selectionBackground': {
110
- background: get(tokens, 'extend.colors.primary.100'),
130
+ background: getToken('extend.colors.primary.100'),
111
131
  },
112
132
  '&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground': {
113
- background: get(tokens, 'extend.colors.primary.200'),
133
+ background: getToken('extend.colors.primary.200'),
114
134
  },
115
135
  '&dark .cm-selectionBackground': {
116
- background: get(tokens, 'extend.colors.primary.700'),
136
+ background: getToken('extend.colors.primary.700'),
117
137
  },
118
138
  '&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground': {
119
- background: get(tokens, 'extend.colors.primary.600'),
139
+ background: getToken('extend.colors.primary.600'),
120
140
  },
121
141
 
122
142
  //
@@ -124,22 +144,27 @@ export const defaultTheme: ThemeStyles = {
124
144
  //
125
145
 
126
146
  '&light .cm-searchMatch': {
127
- backgroundColor: get(tokens, 'extend.colors.yellow.100'),
147
+ backgroundColor: getToken('extend.colors.yellow.100'),
128
148
  },
129
149
  '&dark .cm-searchMatch': {
130
- backgroundColor: get(tokens, 'extend.colors.yellow.700'),
150
+ backgroundColor: getToken('extend.colors.yellow.700'),
131
151
  },
132
152
 
133
153
  //
134
154
  // link
135
155
  //
136
156
  '.cm-link': {
137
- color: get(tokens, 'extend.colors.primary.500'),
138
157
  textDecorationLine: 'underline',
139
158
  textDecorationThickness: '1px',
140
159
  textUnderlineOffset: '2px',
141
160
  borderRadius: '.125rem',
142
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
161
+ fontFamily: getToken('fontFamily.body'),
162
+ },
163
+ '&light .cm-link > span': {
164
+ color: getToken('extend.colors.primary.600'),
165
+ },
166
+ '&dark .cm-link > span': {
167
+ color: getToken('extend.colors.primary.400'),
143
168
  },
144
169
 
145
170
  //
@@ -147,10 +172,10 @@ export const defaultTheme: ThemeStyles = {
147
172
  //
148
173
  '.cm-tooltip': {},
149
174
  '&light .cm-tooltip': {
150
- background: `${get(tokens, 'extend.colors.neutral.100')} !important`,
175
+ background: `${getToken('extend.colors.neutral.100')} !important`,
151
176
  },
152
177
  '&dark .cm-tooltip': {
153
- background: `${get(tokens, 'extend.colors.neutral.900')} !important`,
178
+ background: `${getToken('extend.colors.neutral.900')} !important`,
154
179
  },
155
180
  '.cm-tooltip-below': {},
156
181
 
@@ -167,14 +192,13 @@ export const defaultTheme: ThemeStyles = {
167
192
  },
168
193
  '.cm-tooltip.cm-tooltip-autocomplete > ul > li': {},
169
194
  '.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {},
170
- // TODO(burdon): Can we add a class prefix to avoid adding !important?
171
195
  '.cm-tooltip.cm-tooltip-autocomplete > ul > completion-section': {
172
196
  paddingLeft: '4px !important',
173
197
  borderBottom: 'none !important',
174
- color: get(tokens, 'extend.colors.primary.500'),
198
+ color: getToken('extend.colors.primary.500'),
175
199
  },
176
200
  '.cm-tooltip.cm-completionInfo': {
177
- border: get(tokens, 'extend.colors.neutral.500'),
201
+ border: getToken('extend.colors.neutral.500'),
178
202
  width: '360px !important',
179
203
  margin: '-10px 1px 0 1px',
180
204
  padding: '8px !important',
@@ -183,67 +207,16 @@ export const defaultTheme: ThemeStyles = {
183
207
  display: 'none',
184
208
  },
185
209
  '.cm-completionLabel': {
186
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
210
+ fontFamily: getToken('fontFamily.body'),
187
211
  },
188
212
  '.cm-completionMatchedText': {
189
213
  textDecoration: 'none !important',
190
214
  opacity: 0.5,
191
215
  },
192
216
 
193
- //
194
- // table
195
- //
196
- '.cm-table *': {
197
- fontFamily: `${get(tokens, 'fontFamily.mono', []).join(',')} !important`,
198
- textDecoration: 'none !important',
199
- },
200
- '.cm-table-head': {
201
- padding: '2px 16px 2px 0px',
202
- textAlign: 'left',
203
- borderBottom: `1px solid ${get(tokens, 'extend.colors.primary.500')}`,
204
- color: get(tokens, 'extend.colors.neutral.500'),
205
- },
206
- '.cm-table-cell': {
207
- padding: '2px 16px 2px 0px',
208
- },
209
-
210
- //
211
- // image
212
- //
213
- '.cm-image': {
214
- display: 'block',
215
- height: '0',
216
- },
217
- '.cm-image.cm-loaded-image': {
218
- height: 'auto',
219
- borderTop: '0.5rem solid transparent',
220
- borderBottom: '0.5rem solid transparent',
221
- },
222
-
223
- //
224
- // font size
225
- // TODO(thure): This appears to be the best or only way to set selection caret heights,
226
- // but it's far more verbose than it needs to be.
227
- //
228
- // ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
229
- // const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
230
- //
231
- // acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
232
- // acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
233
- // acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
234
- // return acc;
235
- // }, {}),
236
-
237
217
  // TODO(burdon): Override vars --cm-background.
238
218
  // https://www.npmjs.com/package/codemirror-theme-vars
239
219
 
240
- /**
241
- * Gutters
242
- */
243
- '.cm-gutters': {
244
- background: 'transparent',
245
- },
246
-
247
220
  /**
248
221
  * Panels
249
222
  * TODO(burdon): Needs styling attention (esp. dark mode).
@@ -262,20 +235,20 @@ export const defaultTheme: ThemeStyles = {
262
235
  */
263
236
  '.cm-panels': {},
264
237
  '.cm-panel': {
265
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
238
+ fontFamily: getToken('fontFamily.body'),
266
239
  },
267
240
  '.cm-panel input[type=checkbox]': {
268
241
  marginRight: '0.4rem !important',
269
242
  },
270
243
  '&light .cm-panel': {
271
- background: get(tokens, 'extend.colors.neutral.50'),
244
+ background: getToken('extend.colors.neutral.50'),
272
245
  },
273
246
  '&dark .cm-panel': {
274
- background: get(tokens, 'extend.colors.neutral.850'),
247
+ background: getToken('extend.colors.neutral.850'),
275
248
  },
276
249
  '.cm-button': {
277
250
  margin: '4px',
278
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
251
+ fontFamily: getToken('fontFamily.body'),
279
252
  backgroundImage: 'none',
280
253
  border: 'none',
281
254
  '&:active': {
@@ -283,21 +256,53 @@ export const defaultTheme: ThemeStyles = {
283
256
  },
284
257
  },
285
258
  '&light .cm-button': {
286
- background: get(tokens, 'extend.colors.neutral.100'),
259
+ background: getToken('extend.colors.neutral.100'),
287
260
  '&:hover': {
288
- background: get(tokens, 'extend.colors.neutral.200'),
261
+ background: getToken('extend.colors.neutral.200'),
289
262
  },
290
263
  '&:active': {
291
- background: get(tokens, 'extend.colors.neutral.300'),
264
+ background: getToken('extend.colors.neutral.300'),
292
265
  },
293
266
  },
294
267
  '&dark .cm-button': {
295
- background: get(tokens, 'extend.colors.neutral.800'),
268
+ background: getToken('extend.colors.neutral.800'),
296
269
  '&:hover': {
297
- background: get(tokens, 'extend.colors.neutral.700'),
270
+ background: getToken('extend.colors.neutral.700'),
298
271
  },
299
272
  '&:active': {
300
- background: get(tokens, 'extend.colors.neutral.600'),
273
+ background: getToken('extend.colors.neutral.600'),
301
274
  },
302
275
  },
276
+
277
+ // TODO(burdon): Factor out element specific logic.
278
+
279
+ //
280
+ // table
281
+ //
282
+ '.cm-table *': {
283
+ fontFamily: `${getToken('fontFamily.mono')} !important`,
284
+ textDecoration: 'none !important',
285
+ },
286
+ '.cm-table-head': {
287
+ padding: '2px 16px 2px 0px',
288
+ textAlign: 'left',
289
+ borderBottom: `1px solid ${getToken('extend.colors.primary.500')}`,
290
+ color: getToken('extend.colors.neutral.500'),
291
+ },
292
+ '.cm-table-cell': {
293
+ padding: '2px 16px 2px 0px',
294
+ },
295
+
296
+ //
297
+ // image
298
+ //
299
+ '.cm-image': {
300
+ display: 'block',
301
+ height: '0',
302
+ },
303
+ '.cm-image.cm-loaded-image': {
304
+ height: 'auto',
305
+ borderTop: '0.5rem solid transparent',
306
+ borderBottom: '0.5rem solid transparent',
307
+ },
303
308
  };
@@ -3,14 +3,16 @@
3
3
  //
4
4
 
5
5
  import get from 'lodash.get';
6
- import type { StyleSpec } from 'style-mod';
7
6
 
8
7
  import { tailwindConfig, type TailwindConfig } from '@dxos/react-ui-theme';
9
8
 
10
- export type ThemeStyles = {
11
- [selector: string]: StyleSpec;
12
- };
13
-
14
- export const tokens: TailwindConfig['theme'] = tailwindConfig({}).theme;
9
+ const tokens: TailwindConfig['theme'] = tailwindConfig({}).theme;
15
10
 
16
- export const getToken = (path: string, defaultValue: any = undefined) => get(tokens, path, defaultValue);
11
+ /**
12
+ * @deprecated
13
+ * Replace with CSS vars.
14
+ */
15
+ export const getToken = (path: string, defaultValue?: string | string[]): string => {
16
+ const value = get(tokens, path, defaultValue);
17
+ return value?.toString() ?? '';
18
+ };