@coldsmirk/inkstone-react 0.11.0 → 0.13.0

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.
@@ -1,11 +1,10 @@
1
- import { n as useControlledReconcileSignal, r as CODE_FONT_FAMILY, t as useLatest } from "./use-latest-BhihMdOp.js";
1
+ import { n as useControlledReconcileSignal, t as useLatest } from "./use-latest-BxJHbqOv.js";
2
2
  import { t as useShikiHighlighter } from "./use-shiki-highlighter-CzSQcX2f.js";
3
3
  import { useCallback, useEffect, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { shikiThemeId } from "@coldsmirk/inkstone-core";
6
+ import { DEFAULT_MONACO_OPTIONS, DEFAULT_MONACO_OPTIONS as DEFAULT_MONACO_OPTIONS$1, disabledKeybindings, ensureMonacoHost, installDisabledKeybindings, modelValueMatches, monacoLanguages, reconcileModelValue, registerShikiHighlighting } from "@coldsmirk/inkstone-monaco";
6
7
  import { DiffEditor, Editor, loader } from "@monaco-editor/react";
7
- import { disabledKeybindings, ensureMonacoHost, installDisabledKeybindings, monacoLanguages } from "@coldsmirk/inkstone-monaco";
8
- import { shikiToMonaco } from "@shikijs/monaco";
9
8
  //#region src/editor-face.tsx
10
9
  const FACE_STYLE = {
11
10
  display: "flex",
@@ -21,80 +20,21 @@ function EditorFace({ children }) {
21
20
  });
22
21
  }
23
22
  //#endregion
24
- //#region src/monaco-reconcile.ts
25
- function reconcileModelValue(model, externalValue) {
26
- const value = normalizeModelValue(model, externalValue);
27
- const current = model.getValue();
28
- if (value === current) return;
29
- const shorter = Math.min(current.length, value.length);
30
- let from = 0;
31
- while (from < shorter && current.codePointAt(from) === value.codePointAt(from)) from += 1;
32
- let currentEnd = current.length;
33
- let valueEnd = value.length;
34
- while (currentEnd > from && valueEnd > from && current.codePointAt(currentEnd - 1) === value.codePointAt(valueEnd - 1)) {
35
- currentEnd -= 1;
36
- valueEnd -= 1;
37
- }
38
- const start = model.getPositionAt(from);
39
- const end = model.getPositionAt(currentEnd);
40
- model.applyEdits([{
41
- range: {
42
- startLineNumber: start.lineNumber,
43
- startColumn: start.column,
44
- endLineNumber: end.lineNumber,
45
- endColumn: end.column
46
- },
47
- text: value.slice(from, valueEnd)
48
- }]);
49
- }
50
- function modelValueMatches(model, externalValue) {
51
- return model.getValue() === normalizeModelValue(model, externalValue);
52
- }
53
- function normalizeModelValue(model, externalValue) {
54
- return externalValue.split(/\r\n|\r|\n/).join(model.getEOL());
55
- }
56
- //#endregion
57
23
  //#region src/use-monaco-host.ts
58
- const BOOTSTRAP_KEY = Symbol.for("coldsmirk.inkstone.react.monacoBootstrap");
59
- function bootstrapRegistry() {
24
+ const LOADER_REGISTRY_KEY = Symbol.for("coldsmirk.inkstone.react.monacoLoaders");
25
+ function configuredLoaders() {
60
26
  const host = globalThis;
61
- const existing = host[BOOTSTRAP_KEY];
62
- if (existing?.configuredLoaders && existing.shikiMonacoModules) return existing;
63
- const registry = {
64
- configuredLoaders: /* @__PURE__ */ new WeakSet(),
65
- shikiMonacoModules: /* @__PURE__ */ new WeakSet()
66
- };
67
- host[BOOTSTRAP_KEY] = registry;
68
- return registry;
27
+ const existing = host[LOADER_REGISTRY_KEY];
28
+ if (existing) return existing;
29
+ const created = /* @__PURE__ */ new WeakSet();
30
+ host[LOADER_REGISTRY_KEY] = created;
31
+ return created;
69
32
  }
70
33
  function configureMonacoLoader(targetLoader, monaco) {
71
- const registry = bootstrapRegistry();
72
- if (registry.configuredLoaders.has(targetLoader)) return;
34
+ const registry = configuredLoaders();
35
+ if (registry.has(targetLoader)) return;
73
36
  targetLoader.config({ monaco });
74
- registry.configuredLoaders.add(targetLoader);
75
- }
76
- function registerShikiHighlighting(monaco, highlighter) {
77
- const registry = bootstrapRegistry();
78
- if (registry.shikiMonacoModules.has(monaco)) return;
79
- const canonical = new Set(highlighter.getLoadedLanguages().map((id) => highlighter.getLanguage(id).name));
80
- const registered = new Set(monaco.languages.getLanguages().map((registeredLanguage) => registeredLanguage.id));
81
- for (const lang of canonical) if (!registered.has(lang)) monaco.languages.register({ id: lang });
82
- const shikiThemes = new Set(highlighter.getLoadedThemes());
83
- const originalCreate = monaco.editor.create;
84
- const originalSetTheme = monaco.editor.setTheme;
85
- try {
86
- shikiToMonaco(highlighter, monaco);
87
- const setShikiTheme = monaco.editor.setTheme;
88
- monaco.editor.setTheme = (themeName) => {
89
- if (shikiThemes.has(themeName)) setShikiTheme.call(monaco.editor, themeName);
90
- else originalSetTheme.call(monaco.editor, themeName);
91
- };
92
- } catch (error) {
93
- monaco.editor.create = originalCreate;
94
- monaco.editor.setTheme = originalSetTheme;
95
- throw error;
96
- }
97
- registry.shikiMonacoModules.add(monaco);
37
+ registry.add(targetLoader);
98
38
  }
99
39
  function useMonacoHost(locale, hostOptions) {
100
40
  const [state, setState] = useState("loading");
@@ -119,35 +59,119 @@ function useMonacoHost(locale, hostOptions) {
119
59
  return state;
120
60
  }
121
61
  //#endregion
122
- //#region src/monaco-editor.tsx
123
- const DEFAULT_MONACO_OPTIONS = {
124
- find: { addExtraSpaceOnTop: false },
125
- minimap: { enabled: false },
126
- fontSize: 14,
127
- lineHeight: 1.6,
128
- fontFamily: CODE_FONT_FAMILY,
129
- scrollBeyondLastLine: false,
130
- automaticLayout: true,
131
- renderLineHighlight: "line",
132
- smoothScrolling: true,
133
- padding: {
134
- top: 12,
135
- bottom: 12
136
- },
137
- fixedOverflowWidgets: true,
138
- quickSuggestions: {
139
- other: true,
140
- comments: false,
141
- strings: true
142
- },
143
- wordBasedSuggestions: "off",
144
- tabCompletion: "on",
145
- scrollbar: {
146
- alwaysConsumeMouseWheel: false,
147
- verticalScrollbarSize: 8,
148
- horizontalScrollbarSize: 8
62
+ //#region src/monaco-diff-editor.tsx
63
+ function diffDocumentOptions({ lineWrapping, showLineNumbers, readOnly, collapseUnchanged, fontSize, lineHeight }) {
64
+ const resolved = {
65
+ wordWrap: lineWrapping ? "on" : "off",
66
+ lineNumbers: showLineNumbers ? "on" : "off",
67
+ readOnly,
68
+ hideUnchangedRegions: { enabled: collapseUnchanged }
69
+ };
70
+ if (fontSize !== void 0) resolved.fontSize = fontSize;
71
+ if (lineHeight !== void 0) resolved.lineHeight = lineHeight;
72
+ return resolved;
73
+ }
74
+ function reconcilePane(model, value, reconciling) {
75
+ if (!model) return;
76
+ reconciling.current = true;
77
+ try {
78
+ reconcileModelValue(model, value);
79
+ } finally {
80
+ reconciling.current = false;
149
81
  }
150
- };
82
+ }
83
+ function MonacoDiffEditor({ original, modified, onChange, language = "javascript", dark = false, locale, readOnly = false, collapseUnchanged = false, lineWrapping = false, showLineNumbers = true, fontSize, lineHeight, height = "100%", width, className, options, hostOptions, loading = "Loading editor…", failure = "Editor failed to load", beforeMount, onMount }) {
84
+ const hostState = useMonacoHost(locale, hostOptions);
85
+ const { state: shikiState, highlighterRef } = useShikiHighlighter();
86
+ const beforeMountRef = useLatest(beforeMount);
87
+ const onMountRef = useLatest(onMount);
88
+ const onChangeRef = useLatest(onChange);
89
+ const originalRef = useLatest(original);
90
+ const modifiedRef = useLatest(modified);
91
+ const diffEditorRef = useRef(null);
92
+ const reconcilingRef = useRef(false);
93
+ const modifiedTransitionRef = useRef(false);
94
+ const [reconcileRevision, requestControlledReconcile] = useControlledReconcileSignal();
95
+ const initialValuesRef = useRef({
96
+ original,
97
+ modified
98
+ });
99
+ const mergedOptions = useMemo(() => {
100
+ return {
101
+ ...DEFAULT_MONACO_OPTIONS,
102
+ ...diffDocumentOptions({
103
+ lineWrapping,
104
+ showLineNumbers,
105
+ readOnly,
106
+ collapseUnchanged,
107
+ fontSize,
108
+ lineHeight
109
+ }),
110
+ ...options
111
+ };
112
+ }, [
113
+ lineWrapping,
114
+ showLineNumbers,
115
+ readOnly,
116
+ collapseUnchanged,
117
+ fontSize,
118
+ lineHeight,
119
+ options
120
+ ]);
121
+ useLayoutEffect(() => {
122
+ reconcilePane(diffEditorRef.current?.getOriginalEditor().getModel() ?? null, original, reconcilingRef);
123
+ }, [original]);
124
+ useInsertionEffect(() => {
125
+ const model = diffEditorRef.current?.getModifiedEditor().getModel();
126
+ modifiedTransitionRef.current = model !== null && model !== void 0 && !modelValueMatches(model, modified);
127
+ }, [modified, reconcileRevision]);
128
+ useLayoutEffect(() => {
129
+ try {
130
+ reconcilePane(diffEditorRef.current?.getModifiedEditor().getModel() ?? null, modified, reconcilingRef);
131
+ } finally {
132
+ modifiedTransitionRef.current = false;
133
+ }
134
+ }, [modified, reconcileRevision]);
135
+ if (hostState === "failed") return /* @__PURE__ */ jsx(EditorFace, { children: failure });
136
+ if (hostState === "loading" || shikiState === "loading") return /* @__PURE__ */ jsx(EditorFace, { children: loading });
137
+ const handleBeforeMount = (monaco) => {
138
+ const highlighter = highlighterRef.current;
139
+ if (highlighter) registerShikiHighlighting(monaco, highlighter);
140
+ beforeMountRef.current?.(monaco);
141
+ };
142
+ const handleMount = (diffEditor, monaco) => {
143
+ initialValuesRef.current = {
144
+ original: originalRef.current,
145
+ modified: modifiedRef.current
146
+ };
147
+ diffEditorRef.current = diffEditor;
148
+ const modifiedEditor = diffEditor.getModifiedEditor();
149
+ modifiedEditor.onDidChangeModelContent(() => {
150
+ if (reconcilingRef.current || modifiedTransitionRef.current) return;
151
+ onChangeRef.current?.(modifiedEditor.getValue());
152
+ requestControlledReconcile();
153
+ });
154
+ reconcilePane(diffEditor.getOriginalEditor().getModel(), originalRef.current, reconcilingRef);
155
+ reconcilePane(modifiedEditor.getModel(), modifiedRef.current, reconcilingRef);
156
+ onMountRef.current?.(diffEditor, monaco);
157
+ };
158
+ const theme = shikiState === "ready" ? shikiThemeId(dark) : dark ? "vs-dark" : "vs";
159
+ return /* @__PURE__ */ jsx(DiffEditor, {
160
+ beforeMount: handleBeforeMount,
161
+ className,
162
+ height,
163
+ language,
164
+ loading,
165
+ modified: diffEditorRef.current ? initialValuesRef.current.modified : modified,
166
+ options: mergedOptions,
167
+ original: diffEditorRef.current ? initialValuesRef.current.original : original,
168
+ theme,
169
+ width,
170
+ onMount: handleMount
171
+ });
172
+ }
173
+ //#endregion
174
+ //#region src/monaco-editor.tsx
151
175
  function documentOptions({ placeholder, lineWrapping, showLineNumbers, folding, disableContextMenu, fontSize, lineHeight, tabSize }) {
152
176
  const resolved = {
153
177
  placeholder,
@@ -288,116 +312,4 @@ function MonacoEditor({ value, onChange, language = "javascript", dark = false,
288
312
  });
289
313
  }
290
314
  //#endregion
291
- //#region src/monaco-diff-editor.tsx
292
- function diffDocumentOptions({ lineWrapping, showLineNumbers, readOnly, collapseUnchanged, fontSize, lineHeight }) {
293
- const resolved = {
294
- wordWrap: lineWrapping ? "on" : "off",
295
- lineNumbers: showLineNumbers ? "on" : "off",
296
- readOnly,
297
- hideUnchangedRegions: { enabled: collapseUnchanged }
298
- };
299
- if (fontSize !== void 0) resolved.fontSize = fontSize;
300
- if (lineHeight !== void 0) resolved.lineHeight = lineHeight;
301
- return resolved;
302
- }
303
- function reconcilePane(model, value, reconciling) {
304
- if (!model) return;
305
- reconciling.current = true;
306
- try {
307
- reconcileModelValue(model, value);
308
- } finally {
309
- reconciling.current = false;
310
- }
311
- }
312
- function MonacoDiffEditor({ original, modified, onChange, language = "javascript", dark = false, locale, readOnly = false, collapseUnchanged = false, lineWrapping = false, showLineNumbers = true, fontSize, lineHeight, height = "100%", width, className, options, hostOptions, loading = "Loading editor…", failure = "Editor failed to load", beforeMount, onMount }) {
313
- const hostState = useMonacoHost(locale, hostOptions);
314
- const { state: shikiState, highlighterRef } = useShikiHighlighter();
315
- const beforeMountRef = useLatest(beforeMount);
316
- const onMountRef = useLatest(onMount);
317
- const onChangeRef = useLatest(onChange);
318
- const originalRef = useLatest(original);
319
- const modifiedRef = useLatest(modified);
320
- const diffEditorRef = useRef(null);
321
- const reconcilingRef = useRef(false);
322
- const modifiedTransitionRef = useRef(false);
323
- const [reconcileRevision, requestControlledReconcile] = useControlledReconcileSignal();
324
- const initialValuesRef = useRef({
325
- original,
326
- modified
327
- });
328
- const mergedOptions = useMemo(() => {
329
- return {
330
- ...DEFAULT_MONACO_OPTIONS,
331
- ...diffDocumentOptions({
332
- lineWrapping,
333
- showLineNumbers,
334
- readOnly,
335
- collapseUnchanged,
336
- fontSize,
337
- lineHeight
338
- }),
339
- ...options
340
- };
341
- }, [
342
- lineWrapping,
343
- showLineNumbers,
344
- readOnly,
345
- collapseUnchanged,
346
- fontSize,
347
- lineHeight,
348
- options
349
- ]);
350
- useLayoutEffect(() => {
351
- reconcilePane(diffEditorRef.current?.getOriginalEditor().getModel() ?? null, original, reconcilingRef);
352
- }, [original]);
353
- useInsertionEffect(() => {
354
- const model = diffEditorRef.current?.getModifiedEditor().getModel();
355
- modifiedTransitionRef.current = model !== null && model !== void 0 && !modelValueMatches(model, modified);
356
- }, [modified, reconcileRevision]);
357
- useLayoutEffect(() => {
358
- try {
359
- reconcilePane(diffEditorRef.current?.getModifiedEditor().getModel() ?? null, modified, reconcilingRef);
360
- } finally {
361
- modifiedTransitionRef.current = false;
362
- }
363
- }, [modified, reconcileRevision]);
364
- if (hostState === "failed") return /* @__PURE__ */ jsx(EditorFace, { children: failure });
365
- if (hostState === "loading" || shikiState === "loading") return /* @__PURE__ */ jsx(EditorFace, { children: loading });
366
- const handleBeforeMount = (monaco) => {
367
- const highlighter = highlighterRef.current;
368
- if (highlighter) registerShikiHighlighting(monaco, highlighter);
369
- beforeMountRef.current?.(monaco);
370
- };
371
- const handleMount = (diffEditor, monaco) => {
372
- initialValuesRef.current = {
373
- original: originalRef.current,
374
- modified: modifiedRef.current
375
- };
376
- diffEditorRef.current = diffEditor;
377
- const modifiedEditor = diffEditor.getModifiedEditor();
378
- modifiedEditor.onDidChangeModelContent(() => {
379
- if (reconcilingRef.current || modifiedTransitionRef.current) return;
380
- onChangeRef.current?.(modifiedEditor.getValue());
381
- requestControlledReconcile();
382
- });
383
- reconcilePane(diffEditor.getOriginalEditor().getModel(), originalRef.current, reconcilingRef);
384
- reconcilePane(modifiedEditor.getModel(), modifiedRef.current, reconcilingRef);
385
- onMountRef.current?.(diffEditor, monaco);
386
- };
387
- const theme = shikiState === "ready" ? shikiThemeId(dark) : dark ? "vs-dark" : "vs";
388
- return /* @__PURE__ */ jsx(DiffEditor, {
389
- beforeMount: handleBeforeMount,
390
- className,
391
- height,
392
- language,
393
- loading,
394
- modified: diffEditorRef.current ? initialValuesRef.current.modified : modified,
395
- options: mergedOptions,
396
- original: diffEditorRef.current ? initialValuesRef.current.original : original,
397
- theme,
398
- width,
399
- onMount: handleMount
400
- });
401
- }
402
- //#endregion
403
- export { MonacoEditor as i, MonacoDiffEditor as n, DEFAULT_MONACO_OPTIONS as r, monacoLanguages as t };
315
+ export { MonacoDiffEditor as i, monacoLanguages as n, MonacoEditor as r, DEFAULT_MONACO_OPTIONS$1 as t };
package/dist/monaco.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as MonacoEditorProps, i as MonacoEditor, n as monacoLanguages, o as MonacoDiffEditor, r as DEFAULT_MONACO_OPTIONS, s as MonacoDiffEditorProps, t as MonacoLanguage } from "./monaco-DXifh803.js";
1
+ import { a as MonacoEditorProps, i as MonacoEditor, n as MonacoLanguage, o as MonacoDiffEditor, r as monacoLanguages, s as MonacoDiffEditorProps, t as DEFAULT_MONACO_OPTIONS } from "./monaco-BoTcTdm-.js";
2
2
  export { DEFAULT_MONACO_OPTIONS, MonacoDiffEditor, type MonacoDiffEditorProps, MonacoEditor, type MonacoEditorProps, type MonacoLanguage, monacoLanguages };
package/dist/monaco.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as MonacoEditor, n as MonacoDiffEditor, r as DEFAULT_MONACO_OPTIONS, t as monacoLanguages } from "./monaco-CP5BIXrw.js";
1
+ import { i as MonacoDiffEditor, n as monacoLanguages, r as MonacoEditor, t as DEFAULT_MONACO_OPTIONS } from "./monaco-IkYCUn1k.js";
2
2
  export { DEFAULT_MONACO_OPTIONS, MonacoDiffEditor, MonacoEditor, monacoLanguages };
@@ -1,7 +1,4 @@
1
1
  import { useInsertionEffect, useReducer, useRef } from "react";
2
- //#region src/code-font.ts
3
- const CODE_FONT_FAMILY = "var(--inkstone-font-family-code, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace)";
4
- //#endregion
5
2
  //#region src/use-controlled-reconcile.ts
6
3
  function useControlledReconcileSignal() {
7
4
  return useReducer((revision) => revision + 1, 0);
@@ -16,4 +13,4 @@ function useLatest(value) {
16
13
  return ref;
17
14
  }
18
15
  //#endregion
19
- export { useControlledReconcileSignal as n, CODE_FONT_FAMILY as r, useLatest as t };
16
+ export { useControlledReconcileSignal as n, useLatest as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coldsmirk/inkstone-react",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Drop-in React code editors: a preconfigured Monaco <MonacoEditor> (offline workers, Shiki catppuccin themes, dark switching, opt-in zh-CN UI) and a controlled CodeMirror 6 <CodeMirrorEditor> (catppuccin themes, dark switching, sizing).",
5
5
  "keywords": [
6
6
  "react",
@@ -47,13 +47,10 @@
47
47
  "dist"
48
48
  ],
49
49
  "dependencies": {
50
- "@catppuccin/codemirror": "^1.0.1",
51
- "@catppuccin/palette": "^1.8.0",
52
50
  "@monaco-editor/react": "^4.7.0",
53
- "@shikijs/monaco": "^4.3.1",
54
- "@coldsmirk/inkstone-codemirror": "^0.11.0",
55
- "@coldsmirk/inkstone-core": "^0.11.0",
56
- "@coldsmirk/inkstone-monaco": "^0.11.0"
51
+ "@coldsmirk/inkstone-codemirror": "^0.13.0",
52
+ "@coldsmirk/inkstone-core": "^0.13.0",
53
+ "@coldsmirk/inkstone-monaco": "^0.13.0"
57
54
  },
58
55
  "devDependencies": {
59
56
  "@codemirror/autocomplete": "^6.20.3",
@@ -76,6 +73,29 @@
76
73
  "monaco-editor": "^0.55.1",
77
74
  "react": ">=19"
78
75
  },
76
+ "peerDependenciesMeta": {
77
+ "@codemirror/autocomplete": {
78
+ "optional": true
79
+ },
80
+ "@codemirror/commands": {
81
+ "optional": true
82
+ },
83
+ "@codemirror/language": {
84
+ "optional": true
85
+ },
86
+ "@codemirror/search": {
87
+ "optional": true
88
+ },
89
+ "@codemirror/state": {
90
+ "optional": true
91
+ },
92
+ "@codemirror/view": {
93
+ "optional": true
94
+ },
95
+ "monaco-editor": {
96
+ "optional": true
97
+ }
98
+ },
79
99
  "engines": {
80
100
  "node": ">=24"
81
101
  },