@coldsmirk/inkstone-react 0.8.2

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.
@@ -0,0 +1,390 @@
1
+ import { Extension } from "@codemirror/state";
2
+ import { CodeMirrorLanguage, CodeMirrorLanguage as CodeMirrorLanguage$1, EditorContext, EditorContext as EditorContext$1, codeMirrorLanguages, normalizeContext, searchPhrasesZhCn } from "@coldsmirk/inkstone-codemirror";
3
+ import { ReactNode, RefObject } from "react";
4
+ import { EditorView } from "@codemirror/view";
5
+ import { MonacoHostOptions, MonacoLanguage, MonacoLanguage as MonacoLanguage$1, MonacoUiLocale } from "@coldsmirk/inkstone-monaco";
6
+ import { BeforeMount, OnMount } from "@monaco-editor/react";
7
+ import { editor } from "monaco-editor";
8
+ import { HighlighterCore } from "@coldsmirk/inkstone-core";
9
+
10
+ //#region src/codemirror-editor.d.ts
11
+ interface CodeMirrorEditorProps {
12
+ /**
13
+ * The controlled document text — external changes reconcile into the live editor
14
+ * without resetting the caret.
15
+ */
16
+ value: string;
17
+ onChange?: (value: string) => void;
18
+ /**
19
+ * Language id — lazily loads the matching CodeMirror grammar as its own chunk (only the
20
+ * selected language is fetched, never the whole catalog). For a language outside this set,
21
+ * or for parser options / mixed languages, pass your own support through `extensions`.
22
+ */
23
+ language?: CodeMirrorLanguage$1;
24
+ /**
25
+ * Render-context schema for variable / member autocomplete — currently consumed by the
26
+ * `minijinja` languages, where it makes `{{ }}` / `{% if %}` / `{% for x in %}` suggest the
27
+ * template's context variables and walk member access (`user.address.city`). Pass a JSON Schema
28
+ * (`{ schema }`, e.g. what Rust `schemars` derives) or a sample value (`{ sample }`); it updates
29
+ * reactively without recreating the editor. Memoize/hoist it — a new identity each render
30
+ * re-normalizes and re-dispatches. No effect on languages that don't read it.
31
+ */
32
+ context?: EditorContext$1;
33
+ placeholder?: string;
34
+ /**
35
+ * Soft-wrap long lines.
36
+ *
37
+ * @default false
38
+ */
39
+ lineWrapping?: boolean;
40
+ /**
41
+ * Show the line-number gutter. Fixed at creation, like `lineWrapping` / `placeholder`.
42
+ *
43
+ * @default false
44
+ */
45
+ showLineNumbers?: boolean;
46
+ /**
47
+ * Enable code folding (fold gutter + keymap). Fixed at creation; fold points come from the
48
+ * language, so set `language` too.
49
+ *
50
+ * @default false
51
+ */
52
+ folding?: boolean;
53
+ /**
54
+ * Turn native browser spell-check on. Off by default (CodeMirror's own default, right for
55
+ * code); enable for prose-grade documents like prompt templates. Fixed at creation.
56
+ *
57
+ * @default false
58
+ */
59
+ spellcheck?: boolean;
60
+ /**
61
+ * Enable in-editor search: Ctrl/Cmd-F opens a catppuccin-styled search/replace panel; F3 /
62
+ * Ctrl/Cmd-G cycle matches, Ctrl/Cmd-D selects the next occurrence, Alt-G jumps to a line.
63
+ * The panel speaks CodeMirror's stock English — set `locale="zh-cn"` (or pass
64
+ * `searchPhrasesZhCn` through `extensions`) for Simplified Chinese. Off by default —
65
+ * embedded fields rarely want a search UI. Fixed at creation.
66
+ *
67
+ * @default false
68
+ */
69
+ search?: boolean;
70
+ /**
71
+ * Editor font size in px, applied as a theme extension.
72
+ *
73
+ * @default 14
74
+ */
75
+ fontSize?: number;
76
+ /**
77
+ * Line height, applied as a theme extension on the scroller so content and gutters stay
78
+ * in step. Same convention as `<MonacoEditor>` (Monaco's own): values below 8 multiply the
79
+ * font size (e.g. `1.6` — CSS's unitless line-height), larger values are absolute pixels
80
+ * (e.g. `22`).
81
+ *
82
+ * @default 1.6
83
+ */
84
+ lineHeight?: number;
85
+ /**
86
+ * Tab width in spaces — sets both the displayed tab width (`EditorState.tabSize`) and the
87
+ * indent string inserted on Tab (`indentUnit`), so display and indentation stay in sync.
88
+ */
89
+ tabSize?: number;
90
+ /**
91
+ * Static extensions (language support, keymaps …), fixed for the editor's lifetime.
92
+ * Hoist the array — a new identity per render is ignored by design (create-once).
93
+ */
94
+ extensions?: Extension[];
95
+ /**
96
+ * Extensions swapped in place when the identity changes (theme, language config) —
97
+ * memoize with `useMemo` keyed on what actually changes. Layered after (and so able to
98
+ * override) inkstone's default catppuccin theme.
99
+ */
100
+ dynamicExtensions?: Extension[];
101
+ /**
102
+ * Use the dark catppuccin flavor (macchiato) instead of the light one (latte). The
103
+ * component never reads the OS `prefers-color-scheme`; wire this to your app's
104
+ * color-scheme state — same policy as `<MonacoEditor>`.
105
+ *
106
+ * @default false
107
+ */
108
+ dark?: boolean;
109
+ /**
110
+ * Locale for the phrase tables inkstone ships for CodeMirror's stock UI strings —
111
+ * currently the search / goto-line panel. Unlike Monaco's page-global locale, this is
112
+ * genuinely per-editor (`EditorState.phrases`) and swaps in place. Equivalent to passing
113
+ * `searchPhrasesZhCn` through `extensions`, which stays the framework-agnostic surface.
114
+ *
115
+ * @default "en"
116
+ */
117
+ locale?: "en" | "zh-cn";
118
+ /**
119
+ * Editor height — a number is treated as px. Sizes the editor box and hands overflow to
120
+ * the scroller; omit to grow with content.
121
+ */
122
+ height?: string | number;
123
+ /**
124
+ * Editor width — a number is treated as px. Omit to fill the container.
125
+ */
126
+ width?: string | number;
127
+ className?: string;
128
+ /**
129
+ * Runs once after the editor is created, with the CodeMirror `EditorView` — the imperative
130
+ * handle for focus, dispatch, scrolling, selection, etc. This is CodeMirror's analog of
131
+ * Monaco's `onMount`. Monaco's `loading` / `beforeMount` have no counterpart here: the
132
+ * editor mounts synchronously (no host or editor chunk to await — only the optional
133
+ * `language` grammar streams in behind an already-usable editor), and pre-creation setup is
134
+ * the `extensions` prop rather than a global instance to configure.
135
+ */
136
+ onMount?: (view: EditorView) => void;
137
+ /**
138
+ * Called when the editor gains focus.
139
+ */
140
+ onFocus?: () => void;
141
+ /**
142
+ * Called when the editor loses focus.
143
+ */
144
+ onBlur?: () => void;
145
+ }
146
+ /**
147
+ * A controlled CodeMirror 6 document editor: the standard document extension bundle
148
+ * (line numbers, history, brackets, completion UI — see `documentExtensions`) plus the
149
+ * create-once / reconcile-in-place plumbing of `ControlledEditorHost`, exposed as a plain
150
+ * React component.
151
+ *
152
+ * Ships the catppuccin theme by default (latte / macchiato, flipped by `dark`) and takes
153
+ * `height` / `width` for sizing — parity with `<MonacoEditor>`. Bring your own language
154
+ * support via `extensions`; a theme passed through `dynamicExtensions` overrides the default.
155
+ */
156
+ declare function CodeMirrorEditor({
157
+ value,
158
+ onChange,
159
+ language,
160
+ context,
161
+ placeholder,
162
+ lineWrapping,
163
+ showLineNumbers,
164
+ folding,
165
+ spellcheck,
166
+ search,
167
+ extensions,
168
+ dynamicExtensions,
169
+ dark,
170
+ locale,
171
+ height,
172
+ width,
173
+ fontSize,
174
+ lineHeight,
175
+ tabSize,
176
+ className,
177
+ onMount,
178
+ onFocus,
179
+ onBlur
180
+ }: CodeMirrorEditorProps): ReactNode;
181
+ //#endregion
182
+ //#region src/monaco-editor.d.ts
183
+ /**
184
+ * Baseline construction options shared by every inkstone Monaco editor: no minimap, compact
185
+ * code type, in-place layout tracking, widgets floated above clipping containers, completion
186
+ * tuned for API-assisted editing, thin scrollbars, and an embedded-friendly find widget.
187
+ * Spread these to extend rather than replace: `options={{ ...DEFAULT_MONACO_OPTIONS, wordWrap: "on" }}`.
188
+ */
189
+ declare const DEFAULT_MONACO_OPTIONS: editor.IStandaloneEditorConstructionOptions;
190
+ interface MonacoEditorProps {
191
+ /**
192
+ * The controlled document text.
193
+ */
194
+ value: string;
195
+ onChange?: (value: string) => void;
196
+ /**
197
+ * Monaco language id. Built-in ids autocomplete; any custom-registered id is also accepted.
198
+ *
199
+ * @default "javascript"
200
+ */
201
+ language?: MonacoLanguage$1;
202
+ /**
203
+ * Render with the dark theme. The component never reads the OS `prefers-color-scheme`;
204
+ * wire this to your app's color-scheme state.
205
+ *
206
+ * @default false
207
+ */
208
+ dark?: boolean;
209
+ /**
210
+ * UI locale for Monaco's built-in chrome (context menu, find widget, command palette …).
211
+ * Unlike everything else on this component, the locale is **page-global and locked by the
212
+ * first editor to mount** — Monaco resolves its UI strings once, at module evaluation — so
213
+ * later editors with a different value are ignored. Overrides `hostOptions.locale` (the
214
+ * same knob on the framework-agnostic host layer).
215
+ *
216
+ * @default "en"
217
+ */
218
+ locale?: MonacoUiLocale;
219
+ /**
220
+ * Placeholder shown while the document is empty. Maps to Monaco's native `placeholder`
221
+ * editor option (0.47+); an explicit `options.placeholder` still wins.
222
+ */
223
+ placeholder?: string;
224
+ /**
225
+ * Soft-wrap long lines (Monaco `wordWrap`).
226
+ *
227
+ * @default false
228
+ */
229
+ lineWrapping?: boolean;
230
+ /**
231
+ * Show the line-number gutter (Monaco `lineNumbers`). For relative/interval modes pass an
232
+ * explicit `options.lineNumbers`.
233
+ *
234
+ * @default false
235
+ */
236
+ showLineNumbers?: boolean;
237
+ /**
238
+ * Editor font size in px (Monaco `fontSize`). Omit to keep the inkstone default (14).
239
+ */
240
+ fontSize?: number;
241
+ /**
242
+ * Line height (Monaco `lineHeight`, and its convention): values below 8 multiply the font
243
+ * size (e.g. `1.6`), larger values are absolute pixels (e.g. `22`). `<CodeMirrorEditor>`
244
+ * mirrors the same semantics. Omit to keep the inkstone default (1.6).
245
+ */
246
+ lineHeight?: number;
247
+ /**
248
+ * Tab width in spaces (Monaco `tabSize`).
249
+ *
250
+ * @default 2
251
+ */
252
+ tabSize?: number;
253
+ /**
254
+ * Enable code folding (fold gutter + fold ranges). Unifies the toggle with
255
+ * `<CodeMirrorEditor>`; note Monaco folds by default, so this turns its folding off unless
256
+ * set.
257
+ *
258
+ * @default false
259
+ */
260
+ folding?: boolean;
261
+ /**
262
+ * Disable Monaco's right-click context menu (`contextmenu: false`). Right-clicks then fall
263
+ * through to the browser, so its native menu applies — intercept `contextmenu` on a
264
+ * wrapping element to suppress that as well.
265
+ *
266
+ * @default false
267
+ */
268
+ disableContextMenu?: boolean;
269
+ /**
270
+ * Swallow the find/replace widget's keyboard entries — Ctrl/Cmd+F (find), Ctrl+H and
271
+ * Cmd+Alt+F (replace). Scoped to this editor via a context key: the standalone keybinding
272
+ * service is page-global, so an unscoped rule would rewire every editor on the page.
273
+ * Fixed at creation.
274
+ *
275
+ * @default false
276
+ */
277
+ disableFind?: boolean;
278
+ /**
279
+ * Swallow the command palette's keyboard entry, F1 — Monaco never binds Ctrl+Shift+P
280
+ * (that is a VS Code binding). While the context menu is enabled, its "Command Palette"
281
+ * item still opens the palette; pair with {@link disableContextMenu} to remove every
282
+ * entry point. Fixed at creation.
283
+ *
284
+ * @default false
285
+ */
286
+ disableCommandPalette?: boolean;
287
+ /**
288
+ * Model path — give each logically distinct document its own so view state (cursor,
289
+ * folds) survives remounts.
290
+ */
291
+ path?: string;
292
+ height?: string | number;
293
+ width?: string | number;
294
+ className?: string;
295
+ /**
296
+ * Extra construction options, merged over {@link DEFAULT_MONACO_OPTIONS}.
297
+ */
298
+ options?: editor.IStandaloneEditorConstructionOptions;
299
+ /**
300
+ * Host bring-up options (UI locale, language workers). The Monaco host is a process-wide
301
+ * singleton, so the first mounted editor wins and later values are ignored.
302
+ */
303
+ hostOptions?: MonacoHostOptions;
304
+ /**
305
+ * Shown while the host, highlighter, and editor chunk load.
306
+ *
307
+ * @default "Loading editor…"
308
+ */
309
+ loading?: ReactNode;
310
+ /**
311
+ * Shown when the Monaco host fails to load (e.g. a stale chunk 404 after a redeploy).
312
+ * The failure is not cached by the host singleton, so a fresh mount retries.
313
+ *
314
+ * @default "Editor failed to load"
315
+ */
316
+ failure?: ReactNode;
317
+ /**
318
+ * Runs after inkstone's own pre-mount setup (Shiki theme registration).
319
+ */
320
+ beforeMount?: BeforeMount;
321
+ onMount?: OnMount;
322
+ /**
323
+ * Called when the editor's text area gains focus (Monaco `onDidFocusEditorText`).
324
+ */
325
+ onFocus?: () => void;
326
+ /**
327
+ * Called when the editor's text area loses focus (Monaco `onDidBlurEditorText`).
328
+ */
329
+ onBlur?: () => void;
330
+ }
331
+ /**
332
+ * A preconfigured, offline Monaco editor: bundled workers (no CDN), Shiki catppuccin
333
+ * highlighting with light/dark switching, and sensible document defaults — drop it in with
334
+ * `value` / `onChange` and everything else is wired. The UI speaks Monaco's stock English;
335
+ * pass `hostOptions={{ locale: "zh-cn" }}` for the official Simplified-Chinese chrome.
336
+ *
337
+ * Mounting is gated on the Monaco host and the Shiki highlighter so the first paint already
338
+ * has the right theme; if the highlighter fails to load, the editor falls back to Monaco's
339
+ * built-in themes and stays usable.
340
+ *
341
+ * Do not `import "monaco-editor"` statically elsewhere in the app — that would evaluate
342
+ * Monaco before its UI locale is set (see `ensureMonacoHost`). Type-only imports are fine.
343
+ */
344
+ declare function MonacoEditor({
345
+ value,
346
+ onChange,
347
+ language,
348
+ dark,
349
+ locale,
350
+ placeholder,
351
+ lineWrapping,
352
+ showLineNumbers,
353
+ folding,
354
+ disableContextMenu,
355
+ disableFind,
356
+ disableCommandPalette,
357
+ fontSize,
358
+ lineHeight,
359
+ tabSize,
360
+ path,
361
+ height,
362
+ width,
363
+ className,
364
+ options,
365
+ hostOptions,
366
+ loading,
367
+ failure,
368
+ beforeMount,
369
+ onMount,
370
+ onFocus,
371
+ onBlur
372
+ }: MonacoEditorProps): ReactNode;
373
+ //#endregion
374
+ //#region src/use-shiki-highlighter.d.ts
375
+ type ShikiState = "loading" | "ready" | "failed";
376
+ /**
377
+ * Load the shared Shiki highlighter and expose its lifecycle to gate editor mounting:
378
+ * waiting for `ready` before creating the editor avoids a default-theme flash (and the
379
+ * "theme not found" console error) on first paint; on `failed` the caller falls back to
380
+ * the engine's built-in theme so the editor stays usable.
381
+ *
382
+ * `highlighterRef` is for pre-mount hooks (Monaco `beforeMount`) that must read the
383
+ * instance synchronously before the editor is created.
384
+ */
385
+ declare function useShikiHighlighter(): {
386
+ state: ShikiState;
387
+ highlighterRef: RefObject<HighlighterCore | null>;
388
+ };
389
+ //#endregion
390
+ export { CodeMirrorEditor, type CodeMirrorEditorProps, type CodeMirrorLanguage, DEFAULT_MONACO_OPTIONS, type EditorContext, MonacoEditor, type MonacoEditorProps, type MonacoLanguage, type ShikiState, codeMirrorLanguages, normalizeContext, searchPhrasesZhCn, useShikiHighlighter };