@alauda/react-code-editor 0.1.0-next.20260903.1788425608 → 0.1.0-next.20261021.1792553055

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/index.d.ts CHANGED
@@ -5,7 +5,11 @@ import { RefAttributes } from 'react';
5
5
 
6
6
  export declare const CodeEditor: ForwardRefExoticComponent<CodeEditorProps & RefAttributes<CodeEditorHandle>>;
7
7
 
8
- export declare type CodeEditorAction = 'copy' | 'find' | 'format' | 'fullscreen' | 'redo' | 'undo';
8
+ export declare type CodeEditorAction = 'copy' | 'clear' | 'export' | 'find' | 'format' | 'fullscreen' | 'import' | 'recover' | 'redo' | 'theme' | 'undo';
9
+
10
+ export declare type CodeEditorActionPreset = 'create' | 'view' | 'update' | 'logs';
11
+
12
+ export declare const codeEditorActionPresets: Record<CodeEditorActionPreset, readonly CodeEditorAction[]>;
9
13
 
10
14
  export declare interface CodeEditorDiagnostic {
11
15
  readonly severity: CodeEditorDiagnosticSeverity;
@@ -32,10 +36,19 @@ export declare interface CodeEditorLabels {
32
36
  readonly copy: string;
33
37
  readonly copied: string;
34
38
  readonly copyFailed: string;
39
+ readonly clear?: string;
40
+ readonly export?: string;
35
41
  readonly find: string;
36
42
  readonly format: string;
37
43
  readonly fullscreen: string;
38
44
  readonly exitFullscreen: string;
45
+ readonly import?: string;
46
+ readonly importFailed?: string;
47
+ readonly recover?: string;
48
+ readonly theme?: string;
49
+ readonly themeSystem?: string;
50
+ readonly themeLight?: string;
51
+ readonly themeDark?: string;
39
52
  readonly undo: string;
40
53
  readonly redo: string;
41
54
  readonly loading: string;
@@ -56,15 +69,36 @@ export declare interface CodeEditorProps {
56
69
  readonly readOnly?: boolean;
57
70
  readonly disabled?: boolean;
58
71
  readonly height?: number | string;
72
+ /** Show Monaco's code overview without changing the default for existing consumers. */
73
+ readonly minimap?: boolean;
59
74
  readonly actions?: readonly CodeEditorAction[];
60
75
  readonly labels?: Partial<CodeEditorLabels>;
61
76
  readonly error?: string | null;
62
77
  readonly onDiagnostics?: (diagnostics: readonly CodeEditorDiagnostic[]) => void;
78
+ readonly originalValue?: string;
79
+ /** Controlled comparison view; originalValue remains the consumer's baseline. */
80
+ readonly diffMode?: boolean;
81
+ readonly importAccept?: string;
82
+ readonly exportFileName?: string;
83
+ readonly onImportText?: (text: string, file: File) => void;
84
+ readonly onExport?: (value: string) => void;
85
+ readonly onRecover?: (originalValue: string) => void;
86
+ readonly onClear?: () => void;
87
+ readonly themeMode?: CodeEditorThemeMode;
88
+ readonly onThemeModeChange?: (mode: CodeEditorThemeMode) => void;
89
+ /** Reports package-owned fullscreen state changes to feature consumers. */
90
+ readonly onFullscreenChange?: (fullscreen: boolean) => void;
91
+ /** Feature-owned side panel rendered inside the editor surface. */
92
+ readonly sidebar?: ReactNode;
63
93
  readonly toolbarStart?: ReactNode;
94
+ /** Additional feature-owned controls rendered inside the editor toolbar. */
95
+ readonly toolbarActions?: ReactNode;
64
96
  readonly toolbarEnd?: ReactNode;
65
97
  }
66
98
 
67
- export declare function DiffCodeEditor({ originalValue, value, onChange, language, originalModelPath, modelPath, ariaLabel, readOnly, height, }: DiffCodeEditorProps): JSX.Element;
99
+ export declare type CodeEditorThemeMode = 'system' | 'light' | 'dark';
100
+
101
+ export declare function DiffCodeEditor({ originalValue, value, onChange, language, originalModelPath, modelPath, ariaLabel, readOnly, height, sidebar, }: DiffCodeEditorProps): JSX.Element;
68
102
 
69
103
  export declare interface DiffCodeEditorProps {
70
104
  readonly originalValue: string;
@@ -76,6 +110,8 @@ export declare interface DiffCodeEditorProps {
76
110
  readonly ariaLabel: string;
77
111
  readonly readOnly?: boolean;
78
112
  readonly height?: number | string;
113
+ /** Feature-owned side panel rendered inside the editor surface. */
114
+ readonly sidebar?: ReactNode;
79
115
  }
80
116
 
81
117
  export { }
package/index.js CHANGED
@@ -1,12 +1,12 @@
1
- import { i as loadMonacoRuntime, n as useCodeEditorThemeMode, r as acquireModelOwnership, t as CodeEditor } from "./chunks/CodeEditor-BI8PAcmS.js";
1
+ import { a as loadMonacoRuntime, i as acquireModelOwnership, n as codeEditorActionPresets, r as useCodeEditorThemeMode, t as CodeEditor } from "./chunks/CodeEditor-DhYaoBaC.js";
2
2
  import { DiffEditor } from "@monaco-editor/react";
3
3
  import Alert from "@mui/material/Alert";
4
4
  import Box from "@mui/material/Box";
5
5
  import CircularProgress from "@mui/material/CircularProgress";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
6
7
  import { useEffect, useId, useRef, useState } from "react";
7
- import { jsx } from "react/jsx-runtime";
8
8
  //#region src/DiffCodeEditor.tsx
9
- function DiffCodeEditor({ originalValue, value, onChange, language, originalModelPath, modelPath, ariaLabel, readOnly = false, height = 400 }) {
9
+ function DiffCodeEditor({ originalValue, value, onChange, language, originalModelPath, modelPath, ariaLabel, readOnly = false, height = 400, sidebar }) {
10
10
  const appearanceMode = useCodeEditorThemeMode();
11
11
  const ownerId = useId();
12
12
  const contentListenerRef = useRef(null);
@@ -66,37 +66,55 @@ function DiffCodeEditor({ originalValue, value, onChange, language, originalMode
66
66
  minHeight: 160,
67
67
  overflow: "hidden"
68
68
  },
69
- children: /* @__PURE__ */ jsx(DiffEditor, {
70
- height: "100%",
71
- language,
72
- original: originalValue,
73
- modified: value,
74
- originalModelPath,
75
- modifiedModelPath: modelPath,
76
- theme: appearanceMode === "dark" ? "vs-dark" : "vs",
77
- keepCurrentOriginalModel: true,
78
- keepCurrentModifiedModel: true,
79
- onMount: (editor) => {
80
- contentListenerRef.current?.dispose();
81
- const modifiedEditor = editor.getModifiedEditor();
82
- contentListenerRef.current = modifiedEditor.onDidChangeModelContent(() => {
83
- const nextValue = modifiedEditor.getValue();
84
- if (nextValue !== valueRef.current) onChange?.(nextValue);
85
- });
69
+ children: /* @__PURE__ */ jsxs(Box, {
70
+ sx: {
71
+ display: "flex",
72
+ height: "100%",
73
+ minHeight: 0,
74
+ overflow: "hidden"
86
75
  },
87
- options: {
88
- ariaLabel,
89
- automaticLayout: true,
90
- minimap: { enabled: false },
91
- originalEditable: false,
92
- readOnly,
93
- renderSideBySide: true,
94
- scrollBeyondLastLine: false
95
- }
76
+ children: [/* @__PURE__ */ jsx(Box, {
77
+ sx: {
78
+ flex: sidebar ? "2 1 0%" : "1 1 auto",
79
+ minWidth: 0,
80
+ minHeight: 0,
81
+ overflow: "hidden",
82
+ px: 1.5,
83
+ pb: 1.5
84
+ },
85
+ children: /* @__PURE__ */ jsx(DiffEditor, {
86
+ height: "100%",
87
+ language,
88
+ original: originalValue,
89
+ modified: value,
90
+ originalModelPath,
91
+ modifiedModelPath: modelPath,
92
+ theme: appearanceMode === "dark" ? "vs-dark" : "vs",
93
+ keepCurrentOriginalModel: true,
94
+ keepCurrentModifiedModel: true,
95
+ onMount: (editor) => {
96
+ contentListenerRef.current?.dispose();
97
+ const modifiedEditor = editor.getModifiedEditor();
98
+ contentListenerRef.current = modifiedEditor.onDidChangeModelContent(() => {
99
+ const nextValue = modifiedEditor.getValue();
100
+ if (nextValue !== valueRef.current) onChange?.(nextValue);
101
+ });
102
+ },
103
+ options: {
104
+ ariaLabel,
105
+ automaticLayout: true,
106
+ minimap: { enabled: false },
107
+ originalEditable: false,
108
+ readOnly,
109
+ renderSideBySide: true,
110
+ scrollBeyondLastLine: false
111
+ }
112
+ })
113
+ }), sidebar]
96
114
  })
97
115
  });
98
116
  }
99
117
  //#endregion
100
- export { CodeEditor, DiffCodeEditor };
118
+ export { CodeEditor, DiffCodeEditor, codeEditorActionPresets };
101
119
 
102
120
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/DiffCodeEditor.tsx"],"sourcesContent":["import { DiffEditor } from '@monaco-editor/react';\nimport Alert from '@mui/material/Alert';\nimport Box from '@mui/material/Box';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport { useEffect, useId, useRef, useState } from 'react';\nimport type * as Monaco from 'monaco-editor/esm/vs/editor/editor.main.js';\n\nimport type { CodeEditorLanguage } from './CodeEditor';\nimport { loadMonacoRuntime } from './runtime/loadMonaco';\nimport { acquireModelOwnership } from './runtime/modelOwnership';\nimport { useCodeEditorThemeMode } from './themeAppearance';\n\nexport interface DiffCodeEditorProps {\n readonly originalValue: string;\n readonly value: string;\n readonly onChange?: (value: string) => void;\n readonly language: CodeEditorLanguage;\n readonly originalModelPath: string;\n readonly modelPath: string;\n readonly ariaLabel: string;\n readonly readOnly?: boolean;\n readonly height?: number | string;\n}\n\nexport function DiffCodeEditor({\n originalValue,\n value,\n onChange,\n language,\n originalModelPath,\n modelPath,\n ariaLabel,\n readOnly = false,\n height = 400,\n}: DiffCodeEditorProps) {\n const appearanceMode = useCodeEditorThemeMode();\n const ownerId = useId();\n const contentListenerRef = useRef<Monaco.IDisposable | null>(null);\n const valueRef = useRef(value);\n const [ready, setReady] = useState(false);\n const [runtimeError, setRuntimeError] = useState<string>();\n valueRef.current = value;\n\n useEffect(() => {\n let active = true;\n const releases: Array<() => void> = [];\n setReady(false);\n setRuntimeError(undefined);\n void loadMonacoRuntime()\n .then(monaco => {\n if (!active) return;\n if (originalModelPath === modelPath) {\n throw new Error('Diff editor model paths must be different');\n }\n releases.push(acquireModelOwnership(\n monaco,\n `${ownerId}:original`,\n originalModelPath,\n language,\n ));\n releases.push(acquireModelOwnership(\n monaco,\n `${ownerId}:modified`,\n modelPath,\n language,\n ));\n if (active) setReady(true);\n else releases.splice(0).reverse().forEach(release => release());\n })\n .catch(errorValue => {\n releases.splice(0).reverse().forEach(release => release());\n if (active) {\n setRuntimeError(\n errorValue instanceof Error\n ? errorValue.message\n : String(errorValue),\n );\n }\n });\n return () => {\n active = false;\n contentListenerRef.current?.dispose();\n contentListenerRef.current = null;\n releases.splice(0).reverse().forEach(release => release());\n };\n }, [language, modelPath, originalModelPath, ownerId]);\n\n if (runtimeError) {\n return <Alert severity=\"error\" role=\"alert\">{runtimeError}</Alert>;\n }\n\n if (!ready) {\n return (\n <Box\n role=\"status\"\n aria-label={`Loading ${ariaLabel}`}\n sx={{ display: 'grid', height, minHeight: 160, placeItems: 'center' }}\n >\n <CircularProgress aria-hidden=\"true\" />\n </Box>\n );\n }\n\n return (\n <Box\n role=\"region\"\n aria-label={ariaLabel}\n sx={{ height, minHeight: 160, overflow: 'hidden' }}\n >\n <DiffEditor\n height=\"100%\"\n language={language}\n original={originalValue}\n modified={value}\n originalModelPath={originalModelPath}\n modifiedModelPath={modelPath}\n theme={appearanceMode === 'dark' ? 'vs-dark' : 'vs'}\n keepCurrentOriginalModel\n keepCurrentModifiedModel\n onMount={editor => {\n contentListenerRef.current?.dispose();\n const modifiedEditor = editor.getModifiedEditor();\n contentListenerRef.current = modifiedEditor\n .onDidChangeModelContent(() => {\n const nextValue = modifiedEditor.getValue();\n if (nextValue !== valueRef.current) onChange?.(nextValue);\n });\n }}\n options={{\n ariaLabel,\n automaticLayout: true,\n minimap: { enabled: false },\n originalEditable: false,\n readOnly,\n renderSideBySide: true,\n scrollBeyondLastLine: false,\n }}\n />\n </Box>\n );\n}\n"],"mappings":";;;;;;;;AAwBA,SAAgB,eAAe,EAC7B,eACA,OACA,UACA,UACA,mBACA,WACA,WACA,WAAW,OACX,SAAS,OACa;CACtB,MAAM,iBAAiB,uBAAuB;CAC9C,MAAM,UAAU,MAAM;CACtB,MAAM,qBAAqB,OAAkC,IAAI;CACjE,MAAM,WAAW,OAAO,KAAK;CAC7B,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,CAAC,cAAc,mBAAmB,SAAiB;CACzD,SAAS,UAAU;CAEnB,gBAAgB;EACd,IAAI,SAAS;EACb,MAAM,WAA8B,CAAC;EACrC,SAAS,KAAK;EACd,gBAAgB,KAAA,CAAS;EACzB,kBAAuB,CAAC,CACrB,MAAK,WAAU;GACd,IAAI,CAAC,QAAQ;GACb,IAAI,sBAAsB,WACxB,MAAM,IAAI,MAAM,2CAA2C;GAE7D,SAAS,KAAK,sBACZ,QACA,GAAG,QAAQ,YACX,mBACA,QACF,CAAC;GACD,SAAS,KAAK,sBACZ,QACA,GAAG,QAAQ,YACX,WACA,QACF,CAAC;GACD,IAAI,QAAQ,SAAS,IAAI;QACpB,SAAS,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAQ,YAAW,QAAQ,CAAC;EAChE,CAAC,CAAC,CACD,OAAM,eAAc;GACnB,SAAS,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAQ,YAAW,QAAQ,CAAC;GACzD,IAAI,QACF,gBACE,sBAAsB,QAClB,WAAW,UACX,OAAO,UAAU,CACvB;EAEJ,CAAC;EACH,aAAa;GACX,SAAS;GACT,mBAAmB,SAAS,QAAQ;GACpC,mBAAmB,UAAU;GAC7B,SAAS,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAQ,YAAW,QAAQ,CAAC;EAC3D;CACF,GAAG;EAAC;EAAU;EAAW;EAAmB;CAAO,CAAC;CAEpD,IAAI,cACF,OAAO,oBAAC,OAAD;EAAO,UAAS;EAAQ,MAAK;YAAS;CAAoB,CAAA;CAGnE,IAAI,CAAC,OACH,OACE,oBAAC,KAAD;EACE,MAAK;EACL,cAAY,WAAW;EACvB,IAAI;GAAE,SAAS;GAAQ;GAAQ,WAAW;GAAK,YAAY;EAAS;YAEpE,oBAAC,kBAAD,EAAkB,eAAY,OAAQ,CAAA;CACnC,CAAA;CAIT,OACE,oBAAC,KAAD;EACE,MAAK;EACL,cAAY;EACZ,IAAI;GAAE;GAAQ,WAAW;GAAK,UAAU;EAAS;YAEjD,oBAAC,YAAD;GACE,QAAO;GACG;GACV,UAAU;GACV,UAAU;GACS;GACnB,mBAAmB;GACnB,OAAO,mBAAmB,SAAS,YAAY;GAC/C,0BAAA;GACA,0BAAA;GACA,UAAS,WAAU;IACjB,mBAAmB,SAAS,QAAQ;IACpC,MAAM,iBAAiB,OAAO,kBAAkB;IAChD,mBAAmB,UAAU,eAC1B,8BAA8B;KAC7B,MAAM,YAAY,eAAe,SAAS;KAC1C,IAAI,cAAc,SAAS,SAAS,WAAW,SAAS;IAC1D,CAAC;GACL;GACA,SAAS;IACP;IACA,iBAAiB;IACjB,SAAS,EAAE,SAAS,MAAM;IAC1B,kBAAkB;IAClB;IACA,kBAAkB;IAClB,sBAAsB;GACxB;EACD,CAAA;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/DiffCodeEditor.tsx"],"sourcesContent":["import { DiffEditor } from '@monaco-editor/react';\nimport Alert from '@mui/material/Alert';\nimport Box from '@mui/material/Box';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport { useEffect, useId, useRef, useState, type ReactNode } from 'react';\nimport type * as Monaco from 'monaco-editor/esm/vs/editor/editor.main.js';\n\nimport type { CodeEditorLanguage } from './CodeEditor';\nimport { loadMonacoRuntime } from './runtime/loadMonaco';\nimport { acquireModelOwnership } from './runtime/modelOwnership';\nimport { useCodeEditorThemeMode } from './themeAppearance';\n\nexport interface DiffCodeEditorProps {\n readonly originalValue: string;\n readonly value: string;\n readonly onChange?: (value: string) => void;\n readonly language: CodeEditorLanguage;\n readonly originalModelPath: string;\n readonly modelPath: string;\n readonly ariaLabel: string;\n readonly readOnly?: boolean;\n readonly height?: number | string;\n /** Feature-owned side panel rendered inside the editor surface. */\n readonly sidebar?: ReactNode;\n}\n\nexport function DiffCodeEditor({\n originalValue,\n value,\n onChange,\n language,\n originalModelPath,\n modelPath,\n ariaLabel,\n readOnly = false,\n height = 400,\n sidebar,\n}: DiffCodeEditorProps) {\n const appearanceMode = useCodeEditorThemeMode();\n const ownerId = useId();\n const contentListenerRef = useRef<Monaco.IDisposable | null>(null);\n const valueRef = useRef(value);\n const [ready, setReady] = useState(false);\n const [runtimeError, setRuntimeError] = useState<string>();\n valueRef.current = value;\n\n useEffect(() => {\n let active = true;\n const releases: Array<() => void> = [];\n setReady(false);\n setRuntimeError(undefined);\n void loadMonacoRuntime()\n .then(monaco => {\n if (!active) return;\n if (originalModelPath === modelPath) {\n throw new Error('Diff editor model paths must be different');\n }\n releases.push(acquireModelOwnership(\n monaco,\n `${ownerId}:original`,\n originalModelPath,\n language,\n ));\n releases.push(acquireModelOwnership(\n monaco,\n `${ownerId}:modified`,\n modelPath,\n language,\n ));\n if (active) setReady(true);\n else releases.splice(0).reverse().forEach(release => release());\n })\n .catch(errorValue => {\n releases.splice(0).reverse().forEach(release => release());\n if (active) {\n setRuntimeError(\n errorValue instanceof Error\n ? errorValue.message\n : String(errorValue),\n );\n }\n });\n return () => {\n active = false;\n contentListenerRef.current?.dispose();\n contentListenerRef.current = null;\n releases.splice(0).reverse().forEach(release => release());\n };\n }, [language, modelPath, originalModelPath, ownerId]);\n\n if (runtimeError) {\n return <Alert severity=\"error\" role=\"alert\">{runtimeError}</Alert>;\n }\n\n if (!ready) {\n return (\n <Box\n role=\"status\"\n aria-label={`Loading ${ariaLabel}`}\n sx={{ display: 'grid', height, minHeight: 160, placeItems: 'center' }}\n >\n <CircularProgress aria-hidden=\"true\" />\n </Box>\n );\n }\n\n return (\n <Box\n role=\"region\"\n aria-label={ariaLabel}\n sx={{ height, minHeight: 160, overflow: 'hidden' }}\n >\n <Box sx={{ display: 'flex', height: '100%', minHeight: 0, overflow: 'hidden' }}>\n <Box sx={{ flex: sidebar ? '2 1 0%' : '1 1 auto', minWidth: 0, minHeight: 0, overflow: 'hidden', px: 1.5, pb: 1.5 }}>\n <DiffEditor\n height=\"100%\"\n language={language}\n original={originalValue}\n modified={value}\n originalModelPath={originalModelPath}\n modifiedModelPath={modelPath}\n theme={appearanceMode === 'dark' ? 'vs-dark' : 'vs'}\n keepCurrentOriginalModel\n keepCurrentModifiedModel\n onMount={editor => {\n contentListenerRef.current?.dispose();\n const modifiedEditor = editor.getModifiedEditor();\n contentListenerRef.current = modifiedEditor\n .onDidChangeModelContent(() => {\n const nextValue = modifiedEditor.getValue();\n if (nextValue !== valueRef.current) onChange?.(nextValue);\n });\n }}\n options={{\n ariaLabel,\n automaticLayout: true,\n minimap: { enabled: false },\n originalEditable: false,\n readOnly,\n renderSideBySide: true,\n scrollBeyondLastLine: false,\n }}\n />\n </Box>\n {sidebar}\n </Box>\n </Box>\n );\n}\n"],"mappings":";;;;;;;;AA0BA,SAAgB,eAAe,EAC7B,eACA,OACA,UACA,UACA,mBACA,WACA,WACA,WAAW,OACX,SAAS,KACT,WACsB;CACtB,MAAM,iBAAiB,uBAAuB;CAC9C,MAAM,UAAU,MAAM;CACtB,MAAM,qBAAqB,OAAkC,IAAI;CACjE,MAAM,WAAW,OAAO,KAAK;CAC7B,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,CAAC,cAAc,mBAAmB,SAAiB;CACzD,SAAS,UAAU;CAEnB,gBAAgB;EACd,IAAI,SAAS;EACb,MAAM,WAA8B,CAAC;EACrC,SAAS,KAAK;EACd,gBAAgB,KAAA,CAAS;EACzB,kBAAuB,CAAC,CACrB,MAAK,WAAU;GACd,IAAI,CAAC,QAAQ;GACb,IAAI,sBAAsB,WACxB,MAAM,IAAI,MAAM,2CAA2C;GAE7D,SAAS,KAAK,sBACZ,QACA,GAAG,QAAQ,YACX,mBACA,QACF,CAAC;GACD,SAAS,KAAK,sBACZ,QACA,GAAG,QAAQ,YACX,WACA,QACF,CAAC;GACD,IAAI,QAAQ,SAAS,IAAI;QACpB,SAAS,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAQ,YAAW,QAAQ,CAAC;EAChE,CAAC,CAAC,CACD,OAAM,eAAc;GACnB,SAAS,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAQ,YAAW,QAAQ,CAAC;GACzD,IAAI,QACF,gBACE,sBAAsB,QAClB,WAAW,UACX,OAAO,UAAU,CACvB;EAEJ,CAAC;EACH,aAAa;GACX,SAAS;GACT,mBAAmB,SAAS,QAAQ;GACpC,mBAAmB,UAAU;GAC7B,SAAS,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAQ,YAAW,QAAQ,CAAC;EAC3D;CACF,GAAG;EAAC;EAAU;EAAW;EAAmB;CAAO,CAAC;CAEpD,IAAI,cACF,OAAO,oBAAC,OAAD;EAAO,UAAS;EAAQ,MAAK;YAAS;CAAoB,CAAA;CAGnE,IAAI,CAAC,OACH,OACE,oBAAC,KAAD;EACE,MAAK;EACL,cAAY,WAAW;EACvB,IAAI;GAAE,SAAS;GAAQ;GAAQ,WAAW;GAAK,YAAY;EAAS;YAEpE,oBAAC,kBAAD,EAAkB,eAAY,OAAQ,CAAA;CACnC,CAAA;CAIT,OACE,oBAAC,KAAD;EACE,MAAK;EACL,cAAY;EACZ,IAAI;GAAE;GAAQ,WAAW;GAAK,UAAU;EAAS;YAEjD,qBAAC,KAAD;GAAK,IAAI;IAAE,SAAS;IAAQ,QAAQ;IAAQ,WAAW;IAAG,UAAU;GAAS;aAA7E,CACE,oBAAC,KAAD;IAAK,IAAI;KAAE,MAAM,UAAU,WAAW;KAAY,UAAU;KAAG,WAAW;KAAG,UAAU;KAAU,IAAI;KAAK,IAAI;IAAI;cAChH,oBAAC,YAAD;KACF,QAAO;KACG;KACV,UAAU;KACV,UAAU;KACS;KACnB,mBAAmB;KACnB,OAAO,mBAAmB,SAAS,YAAY;KAC/C,0BAAA;KACA,0BAAA;KACA,UAAS,WAAU;MACjB,mBAAmB,SAAS,QAAQ;MACpC,MAAM,iBAAiB,OAAO,kBAAkB;MAChD,mBAAmB,UAAU,eAC1B,8BAA8B;OAC7B,MAAM,YAAY,eAAe,SAAS;OAC1C,IAAI,cAAc,SAAS,SAAS,WAAW,SAAS;MAC1D,CAAC;KACL;KACA,SAAS;MACP;MACA,iBAAiB;MACjB,SAAS,EAAE,SAAS,MAAM;MAC1B,kBAAkB;MAClB;MACA,kBAAkB;MAClB,sBAAsB;KACxB;IACG,CAAA;GACE,CAAA,GACJ,OACE;;CACF,CAAA;AAET"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alauda/react-code-editor",
3
- "version": "0.1.0-next.20260903.1788425608",
3
+ "version": "0.1.0-next.20261021.1792553055",
4
4
  "description": "React Monaco code editor with schema-aware YAML support.",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -36,6 +36,7 @@
36
36
  "peerDependencies": {
37
37
  "@emotion/react": "^11.0.0",
38
38
  "@emotion/styled": "^11.0.0",
39
+ "@mui/icons-material": "^9.2.0",
39
40
  "@mui/material": "^9.2.0",
40
41
  "react": "^18.0.0 || ^19.0.0",
41
42
  "react-dom": "^18.0.0 || ^19.0.0"
package/yaml/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { ForwardRefExoticComponent } from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import { RefAttributes } from 'react';
4
4
 
5
- declare type CodeEditorAction = 'copy' | 'find' | 'format' | 'fullscreen' | 'redo' | 'undo';
5
+ declare type CodeEditorAction = 'copy' | 'clear' | 'export' | 'find' | 'format' | 'fullscreen' | 'import' | 'recover' | 'redo' | 'theme' | 'undo';
6
6
 
7
7
  declare interface CodeEditorDiagnostic {
8
8
  readonly severity: CodeEditorDiagnosticSeverity;
@@ -33,10 +33,19 @@ declare interface CodeEditorLabels {
33
33
  readonly copy: string;
34
34
  readonly copied: string;
35
35
  readonly copyFailed: string;
36
+ readonly clear?: string;
37
+ readonly export?: string;
36
38
  readonly find: string;
37
39
  readonly format: string;
38
40
  readonly fullscreen: string;
39
41
  readonly exitFullscreen: string;
42
+ readonly import?: string;
43
+ readonly importFailed?: string;
44
+ readonly recover?: string;
45
+ readonly theme?: string;
46
+ readonly themeSystem?: string;
47
+ readonly themeLight?: string;
48
+ readonly themeDark?: string;
40
49
  readonly undo: string;
41
50
  readonly redo: string;
42
51
  readonly loading: string;
@@ -57,14 +66,35 @@ declare interface CodeEditorProps {
57
66
  readonly readOnly?: boolean;
58
67
  readonly disabled?: boolean;
59
68
  readonly height?: number | string;
69
+ /** Show Monaco's code overview without changing the default for existing consumers. */
70
+ readonly minimap?: boolean;
60
71
  readonly actions?: readonly CodeEditorAction[];
61
72
  readonly labels?: Partial<CodeEditorLabels>;
62
73
  readonly error?: string | null;
63
74
  readonly onDiagnostics?: (diagnostics: readonly CodeEditorDiagnostic[]) => void;
75
+ readonly originalValue?: string;
76
+ /** Controlled comparison view; originalValue remains the consumer's baseline. */
77
+ readonly diffMode?: boolean;
78
+ readonly importAccept?: string;
79
+ readonly exportFileName?: string;
80
+ readonly onImportText?: (text: string, file: File) => void;
81
+ readonly onExport?: (value: string) => void;
82
+ readonly onRecover?: (originalValue: string) => void;
83
+ readonly onClear?: () => void;
84
+ readonly themeMode?: CodeEditorThemeMode;
85
+ readonly onThemeModeChange?: (mode: CodeEditorThemeMode) => void;
86
+ /** Reports package-owned fullscreen state changes to feature consumers. */
87
+ readonly onFullscreenChange?: (fullscreen: boolean) => void;
88
+ /** Feature-owned side panel rendered inside the editor surface. */
89
+ readonly sidebar?: ReactNode;
64
90
  readonly toolbarStart?: ReactNode;
91
+ /** Additional feature-owned controls rendered inside the editor toolbar. */
92
+ readonly toolbarActions?: ReactNode;
65
93
  readonly toolbarEnd?: ReactNode;
66
94
  }
67
95
 
96
+ declare type CodeEditorThemeMode = 'system' | 'light' | 'dark';
97
+
68
98
  export declare type JsonPrimitive = boolean | number | string | null;
69
99
 
70
100
  export declare type JsonValue = JsonPrimitive | readonly JsonValue[] | {
package/yaml/index.js CHANGED
@@ -1,22 +1,26 @@
1
- import { a as getSharedRuntimeState, i as loadMonacoRuntime, t as CodeEditor } from "../chunks/CodeEditor-BI8PAcmS.js";
1
+ import { a as loadMonacoRuntime, o as getSharedRuntimeState, t as CodeEditor } from "../chunks/CodeEditor-DhYaoBaC.js";
2
2
  import Alert from "@mui/material/Alert";
3
3
  import Box from "@mui/material/Box";
4
4
  import CircularProgress from "@mui/material/CircularProgress";
5
- import { forwardRef, useEffect, useId, useRef, useState } from "react";
6
5
  import { jsx } from "react/jsx-runtime";
6
+ import { forwardRef, useEffect, useId, useRef, useState } from "react";
7
7
  //#region src/yaml/yamlRuntime.ts
8
8
  function getYamlRuntime() {
9
9
  const runtime = getSharedRuntimeState();
10
10
  runtime.yaml ??= { owners: /* @__PURE__ */ new Map() };
11
11
  return runtime.yaml;
12
12
  }
13
+ function schemaUri(id, modelPath) {
14
+ const encode = (value) => Array.from(new TextEncoder().encode(value), (byte) => byte.toString(16).padStart(2, "0")).join("");
15
+ return `alauda://schemas/${encode(id)}/${encode(modelPath)}`;
16
+ }
13
17
  function yamlOptions(owners) {
14
18
  const registrations = [...owners];
15
19
  const schemas = /* @__PURE__ */ new Map();
16
20
  for (const registration of registrations) for (const schema of registration.schemas) {
17
21
  const key = `${schema.id}\u0000${schema.modelPath}`;
18
22
  schemas.set(key, {
19
- uri: `alauda://schemas/${encodeURIComponent(schema.id)}`,
23
+ uri: schemaUri(schema.id, schema.modelPath),
20
24
  fileMatch: [schema.modelPath],
21
25
  schema: schema.schema
22
26
  });
package/yaml/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/yaml/yamlRuntime.ts","../../../src/yaml/ResourceYamlEditor.tsx"],"sourcesContent":["import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.main.js';\nimport type {\n MonacoYaml,\n MonacoYamlOptions,\n} from 'monaco-yaml';\n\nimport { getSharedRuntimeState } from '../runtime/runtimeState';\nimport type { YamlSchemaRegistration } from './types';\n\ninterface YamlOwnerRegistration {\n readonly modelPath: string;\n readonly schemas: readonly YamlSchemaRegistration[];\n readonly isKubernetes: boolean;\n}\n\ninterface SharedYamlRuntime {\n controller?: MonacoYaml;\n promise?: Promise<void>;\n updatePromise?: Promise<void>;\n readonly owners: Map<string, YamlOwnerRegistration>;\n}\n\nfunction getYamlRuntime(): SharedYamlRuntime {\n const runtime = getSharedRuntimeState();\n runtime.yaml ??= { owners: new Map() } satisfies SharedYamlRuntime;\n return runtime.yaml as SharedYamlRuntime;\n}\n\nfunction yamlOptions(\n owners: Iterable<YamlOwnerRegistration>,\n): MonacoYamlOptions {\n const registrations = [...owners];\n const schemas = new Map<string, {\n uri: string;\n fileMatch: string[];\n schema: import('monaco-yaml').JSONSchema;\n }>();\n for (const registration of registrations) {\n for (const schema of registration.schemas) {\n const key = `${schema.id}\\u0000${schema.modelPath}`;\n schemas.set(key, {\n uri: `alauda://schemas/${encodeURIComponent(schema.id)}`,\n fileMatch: [schema.modelPath],\n schema: schema.schema as import('monaco-yaml').JSONSchema,\n });\n }\n }\n return {\n completion: true,\n enableSchemaRequest: false,\n format: { enable: true, printWidth: 120 },\n hover: true,\n isKubernetes: registrations.some(item => item.isKubernetes),\n validate: true,\n yamlVersion: '1.2',\n schemas: [...schemas.values()],\n };\n}\n\nasync function updateYamlRuntime(): Promise<void> {\n const runtime = getYamlRuntime();\n runtime.updatePromise = (runtime.updatePromise ?? Promise.resolve())\n .catch(() => undefined)\n .then(async () => {\n await runtime.controller?.update(yamlOptions(runtime.owners.values()));\n });\n await runtime.updatePromise;\n}\n\nexport function ensureYamlRuntime(monaco: typeof Monaco): Promise<void> {\n const runtime = getYamlRuntime();\n if (runtime.promise) return runtime.promise;\n const promise = import('monaco-yaml').then(({ configureMonacoYaml }) => {\n runtime.controller = configureMonacoYaml(\n monaco,\n yamlOptions(runtime.owners.values()),\n );\n });\n runtime.promise = promise;\n void promise.catch(() => {\n if (runtime.promise === promise) runtime.promise = undefined;\n });\n return promise;\n}\n\nfunction schemaSignature(\n schemas: readonly YamlSchemaRegistration[],\n): string {\n return JSON.stringify(schemas.map(schema => ({\n id: schema.id,\n modelPath: schema.modelPath,\n schema: schema.schema,\n })));\n}\n\nexport async function registerYamlOwner(\n ownerId: string,\n registration: YamlOwnerRegistration,\n): Promise<() => void> {\n const runtime = getYamlRuntime();\n const conflict = [...runtime.owners.entries()].find(([otherOwner, item]) => (\n otherOwner !== ownerId\n && item.modelPath === registration.modelPath\n && schemaSignature(item.schemas) !== schemaSignature(registration.schemas)\n ));\n if (conflict) {\n throw new Error(\n `Conflicting YAML schema ownership for ${registration.modelPath}`,\n );\n }\n\n runtime.owners.set(ownerId, registration);\n try {\n await updateYamlRuntime();\n } catch (error) {\n runtime.owners.delete(ownerId);\n void updateYamlRuntime();\n throw error;\n }\n let active = true;\n return () => {\n if (!active) return;\n active = false;\n runtime.owners.delete(ownerId);\n void updateYamlRuntime();\n };\n}\n","import Alert from '@mui/material/Alert';\nimport Box from '@mui/material/Box';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\n\nimport {\n CodeEditor,\n type CodeEditorHandle,\n type CodeEditorProps,\n} from '../CodeEditor';\nimport { loadMonacoRuntime } from '../runtime/loadMonaco';\nimport type { YamlSchemaRegistration } from './types';\nimport {\n ensureYamlRuntime,\n registerYamlOwner,\n} from './yamlRuntime';\n\nexport interface ResourceYamlEditorProps extends Omit<\n CodeEditorProps,\n 'language'\n> {\n readonly schemas?: readonly YamlSchemaRegistration[];\n readonly isKubernetes?: boolean;\n}\n\nconst emptySchemas: readonly YamlSchemaRegistration[] = [];\n\nexport const ResourceYamlEditor = forwardRef<\nCodeEditorHandle,\nResourceYamlEditorProps\n>(function ResourceYamlEditor({\n schemas = emptySchemas,\n isKubernetes = false,\n modelPath,\n height = 400,\n ...props\n}, ref) {\n const ownerId = useId();\n const schemaKey = JSON.stringify(schemas);\n const schemasRef = useRef({ key: schemaKey, value: schemas });\n if (schemasRef.current.key !== schemaKey) {\n schemasRef.current = { key: schemaKey, value: schemas };\n }\n const stableSchemas = schemasRef.current.value;\n const [ready, setReady] = useState(false);\n const [runtimeError, setRuntimeError] = useState<string>();\n\n useEffect(() => {\n let active = true;\n let release: (() => void) | undefined;\n void loadMonacoRuntime()\n .then(async monaco => {\n await ensureYamlRuntime(monaco);\n if (!active) return;\n release = await registerYamlOwner(ownerId, {\n modelPath,\n schemas: stableSchemas,\n isKubernetes,\n });\n if (active) {\n setRuntimeError(undefined);\n setReady(true);\n } else {\n release();\n }\n })\n .catch(error => {\n if (active) {\n setReady(false);\n setRuntimeError(\n error instanceof Error ? error.message : String(error),\n );\n }\n });\n return () => {\n active = false;\n release?.();\n };\n }, [isKubernetes, modelPath, ownerId, stableSchemas]);\n\n if (runtimeError) {\n return <Alert severity=\"error\" role=\"alert\">{runtimeError}</Alert>;\n }\n\n if (!ready) {\n return (\n <Box\n role=\"status\"\n aria-label=\"Loading YAML editor\"\n sx={{ display: 'grid', height, minHeight: 160, placeItems: 'center' }}\n >\n <CircularProgress aria-hidden=\"true\" />\n </Box>\n );\n }\n\n return (\n <CodeEditor\n {...props}\n ref={ref}\n height={height}\n language=\"yaml\"\n modelPath={modelPath}\n />\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/yaml/yamlRuntime.ts","../../../src/yaml/ResourceYamlEditor.tsx"],"sourcesContent":["import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.main.js';\nimport type {\n MonacoYaml,\n MonacoYamlOptions,\n} from 'monaco-yaml';\n\nimport { getSharedRuntimeState } from '../runtime/runtimeState';\nimport type { YamlSchemaRegistration } from './types';\n\ninterface YamlOwnerRegistration {\n readonly modelPath: string;\n readonly schemas: readonly YamlSchemaRegistration[];\n readonly isKubernetes: boolean;\n}\n\ninterface SharedYamlRuntime {\n controller?: MonacoYaml;\n promise?: Promise<void>;\n updatePromise?: Promise<void>;\n readonly owners: Map<string, YamlOwnerRegistration>;\n}\n\nfunction getYamlRuntime(): SharedYamlRuntime {\n const runtime = getSharedRuntimeState();\n runtime.yaml ??= { owners: new Map() } satisfies SharedYamlRuntime;\n return runtime.yaml as SharedYamlRuntime;\n}\n\n// Percent-encoded slashes are decoded by the language service's URI normalizer.\n// Use an ASCII identity that remains identical before/after normalization, and\n// include the model so same-GVK editors cannot overwrite each other's schema.\nfunction schemaUri(id: string, modelPath: string): string {\n const encode = (value: string) => Array.from(new TextEncoder().encode(value), byte => byte.toString(16).padStart(2, '0')).join('');\n return `alauda://schemas/${encode(id)}/${encode(modelPath)}`;\n}\n\nfunction yamlOptions(\n owners: Iterable<YamlOwnerRegistration>,\n): MonacoYamlOptions {\n const registrations = [...owners];\n const schemas = new Map<string, {\n uri: string;\n fileMatch: string[];\n schema: import('monaco-yaml').JSONSchema;\n }>();\n for (const registration of registrations) {\n for (const schema of registration.schemas) {\n const key = `${schema.id}\\u0000${schema.modelPath}`;\n schemas.set(key, {\n uri: schemaUri(schema.id, schema.modelPath),\n fileMatch: [schema.modelPath],\n schema: schema.schema as import('monaco-yaml').JSONSchema,\n });\n }\n }\n return {\n completion: true,\n enableSchemaRequest: false,\n format: { enable: true, printWidth: 120 },\n hover: true,\n isKubernetes: registrations.some(item => item.isKubernetes),\n validate: true,\n yamlVersion: '1.2',\n schemas: [...schemas.values()],\n };\n}\n\nasync function updateYamlRuntime(): Promise<void> {\n const runtime = getYamlRuntime();\n runtime.updatePromise = (runtime.updatePromise ?? Promise.resolve())\n .catch(() => undefined)\n .then(async () => {\n await runtime.controller?.update(yamlOptions(runtime.owners.values()));\n });\n await runtime.updatePromise;\n}\n\nexport function ensureYamlRuntime(monaco: typeof Monaco): Promise<void> {\n const runtime = getYamlRuntime();\n if (runtime.promise) return runtime.promise;\n const promise = import('monaco-yaml').then(({ configureMonacoYaml }) => {\n runtime.controller = configureMonacoYaml(\n monaco,\n yamlOptions(runtime.owners.values()),\n );\n });\n runtime.promise = promise;\n void promise.catch(() => {\n if (runtime.promise === promise) runtime.promise = undefined;\n });\n return promise;\n}\n\nfunction schemaSignature(\n schemas: readonly YamlSchemaRegistration[],\n): string {\n return JSON.stringify(schemas.map(schema => ({\n id: schema.id,\n modelPath: schema.modelPath,\n schema: schema.schema,\n })));\n}\n\nexport async function registerYamlOwner(\n ownerId: string,\n registration: YamlOwnerRegistration,\n): Promise<() => void> {\n const runtime = getYamlRuntime();\n const conflict = [...runtime.owners.entries()].find(([otherOwner, item]) => (\n otherOwner !== ownerId\n && item.modelPath === registration.modelPath\n && schemaSignature(item.schemas) !== schemaSignature(registration.schemas)\n ));\n if (conflict) {\n throw new Error(\n `Conflicting YAML schema ownership for ${registration.modelPath}`,\n );\n }\n\n runtime.owners.set(ownerId, registration);\n try {\n await updateYamlRuntime();\n } catch (error) {\n runtime.owners.delete(ownerId);\n void updateYamlRuntime();\n throw error;\n }\n let active = true;\n return () => {\n if (!active) return;\n active = false;\n runtime.owners.delete(ownerId);\n void updateYamlRuntime();\n };\n}\n","import Alert from '@mui/material/Alert';\nimport Box from '@mui/material/Box';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\n\nimport {\n CodeEditor,\n type CodeEditorHandle,\n type CodeEditorProps,\n} from '../CodeEditor';\nimport { loadMonacoRuntime } from '../runtime/loadMonaco';\nimport type { YamlSchemaRegistration } from './types';\nimport {\n ensureYamlRuntime,\n registerYamlOwner,\n} from './yamlRuntime';\n\nexport interface ResourceYamlEditorProps extends Omit<\n CodeEditorProps,\n 'language'\n> {\n readonly schemas?: readonly YamlSchemaRegistration[];\n readonly isKubernetes?: boolean;\n}\n\nconst emptySchemas: readonly YamlSchemaRegistration[] = [];\n\nexport const ResourceYamlEditor = forwardRef<\nCodeEditorHandle,\nResourceYamlEditorProps\n>(function ResourceYamlEditor({\n schemas = emptySchemas,\n isKubernetes = false,\n modelPath,\n height = 400,\n ...props\n}, ref) {\n const ownerId = useId();\n const schemaKey = JSON.stringify(schemas);\n const schemasRef = useRef({ key: schemaKey, value: schemas });\n if (schemasRef.current.key !== schemaKey) {\n schemasRef.current = { key: schemaKey, value: schemas };\n }\n const stableSchemas = schemasRef.current.value;\n const [ready, setReady] = useState(false);\n const [runtimeError, setRuntimeError] = useState<string>();\n\n useEffect(() => {\n let active = true;\n let release: (() => void) | undefined;\n void loadMonacoRuntime()\n .then(async monaco => {\n await ensureYamlRuntime(monaco);\n if (!active) return;\n release = await registerYamlOwner(ownerId, {\n modelPath,\n schemas: stableSchemas,\n isKubernetes,\n });\n if (active) {\n setRuntimeError(undefined);\n setReady(true);\n } else {\n release();\n }\n })\n .catch(error => {\n if (active) {\n setReady(false);\n setRuntimeError(\n error instanceof Error ? error.message : String(error),\n );\n }\n });\n return () => {\n active = false;\n release?.();\n };\n }, [isKubernetes, modelPath, ownerId, stableSchemas]);\n\n if (runtimeError) {\n return <Alert severity=\"error\" role=\"alert\">{runtimeError}</Alert>;\n }\n\n if (!ready) {\n return (\n <Box\n role=\"status\"\n aria-label=\"Loading YAML editor\"\n sx={{ display: 'grid', height, minHeight: 160, placeItems: 'center' }}\n >\n <CircularProgress aria-hidden=\"true\" />\n </Box>\n );\n }\n\n return (\n <CodeEditor\n {...props}\n ref={ref}\n height={height}\n language=\"yaml\"\n modelPath={modelPath}\n />\n );\n});\n"],"mappings":"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"}