@haklex/rich-ext-code-snippet 0.0.80 → 0.0.82

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/index.mjs CHANGED
@@ -1,476 +1,416 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { g as getLanguageFromFilename, m as modal, s as semanticClassNames, a as modalTitlebar, b as modalTitle, c as modalIconButton, d as modalBody, e as modalSidebar, f as sidebarHeader, h as sidebarAddButton, i as fileList, j as dragOverlay, k as fileIcon, l as fileName, n as fileItem, o as modalEditor, p as breadcrumb, q as breadcrumbLeft, r as breadcrumbName, t as breadcrumbLang, u as editorContainer, v as fileDragHandle, w as renameInput, x as fileDelete, y as codeSnippetDialogPopup, z as editContainer, C as CodeSnippetRenderer, A as editOverlay, B as editLabel, $ as $isCodeSnippetNode, D as CodeSnippetNode } from "./CodeSnippetNode-BmRM_Ma7.js";
5
- import { E } from "./CodeSnippetNode-BmRM_Ma7.js";
6
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
1
+ import { A as modalTitlebar, C as fileName, D as modalIconButton, E as modalEditor, M as semanticClassNames, N as sidebarAddButton, O as modalSidebar, P as sidebarHeader, S as fileList, T as modalBody, _ as editorContainer, a as _defineProperty, b as fileIcon, c as breadcrumb, f as codeSnippetDialogPopup, g as editOverlay, h as editLabel, i as CodeSnippetNode, j as renameInput, k as modalTitle, m as editContainer, n as $createCodeSnippetNode, o as CodeSnippetRenderer, p as dragOverlay, r as $isCodeSnippetNode, s as getLanguageFromFilename, t as CODE_SNIPPET_BLOCK_TRANSFORMER, u as breadcrumbLeft, w as modal, x as fileItem, y as fileDragHandle } from "./transformer-CCg3Ky-e.js";
7
2
  import { useColorScheme } from "@haklex/rich-editor";
8
3
  import { presentDialog } from "@haklex/rich-editor-ui";
9
4
  import { usePortalTheme } from "@haklex/rich-style-token";
10
- import { X, Plus, GripVertical, Trash2, Pencil, FileCode } from "lucide-react";
11
- import { useState, useRef, useEffect, useCallback, useMemo, useContext, createContext, createElement } from "react";
12
- import { history, defaultKeymap, historyKeymap, indentWithTab } from "@codemirror/commands";
5
+ import { FileCode, GripVertical, Pencil, Plus, Trash2, X } from "lucide-react";
6
+ import { createContext, createElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
7
+ import { defaultKeymap, history, historyKeymap, indentWithTab } from "@codemirror/commands";
13
8
  import { Compartment, EditorState } from "@codemirror/state";
14
9
  import { EditorView, keymap, lineNumbers } from "@codemirror/view";
15
- import { useSensors, useSensor, PointerSensor, DndContext, closestCenter, DragOverlay } from "@dnd-kit/core";
16
- import { arrayMove, SortableContext, verticalListSortingStrategy, useSortable } from "@dnd-kit/sortable";
10
+ import { DndContext, DragOverlay, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
11
+ import { SortableContext, arrayMove, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
17
12
  import { CSS } from "@dnd-kit/utilities";
18
13
  import { getThemeExtensions, loadLanguageExtension } from "@haklex/cm-editor";
19
14
  import { normalizeLanguage } from "@haklex/rich-renderer-codeblock/constants";
20
15
  import { FileIcon } from "@haklex/rich-renderer-codeblock/icons";
21
16
  import { createPortal } from "react-dom";
17
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
18
  import { $getNodeByKey, $insertNodes } from "lexical";
23
- import { CODE_SNIPPET_BLOCK_TRANSFORMER } from "@haklex/rich-headless/transformers";
24
- const SortableFileItem = ({
25
- file,
26
- isActive,
27
- isEditing,
28
- editValue,
29
- canDelete,
30
- onSelect,
31
- onStartRename,
32
- onEditChange,
33
- onCommitRename,
34
- onCancelRename,
35
- onDelete
36
- }) => {
37
- const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
38
- id: file.filename
39
- });
40
- const style = {
41
- transform: CSS.Transform.toString(transform),
42
- transition
43
- };
44
- return /* @__PURE__ */ jsxs(
45
- "div",
46
- {
47
- className: `${fileItem({ active: isActive, dragging: isDragging })} ${semanticClassNames.fileItem} ${isActive ? semanticClassNames.fileItemActive : ""} ${isDragging ? semanticClassNames.fileItemDragging : ""}`.trim(),
48
- ref: setNodeRef,
49
- style,
50
- onClick: onSelect,
51
- onDoubleClick: onStartRename,
52
- children: [
53
- /* @__PURE__ */ jsx(
54
- "span",
55
- {
56
- className: `${fileDragHandle} ${semanticClassNames.fileDragHandle}`,
57
- ...attributes,
58
- ...listeners,
59
- onClick: (e) => e.stopPropagation(),
60
- children: /* @__PURE__ */ jsx(GripVertical, { size: 12 })
61
- }
62
- ),
63
- /* @__PURE__ */ jsx(
64
- FileIcon,
65
- {
66
- className: `${fileIcon} ${semanticClassNames.fileIcon}`,
67
- filename: file.filename,
68
- size: 14
69
- }
70
- ),
71
- isEditing ? /* @__PURE__ */ jsx(
72
- "input",
73
- {
74
- autoFocus: true,
75
- className: `${renameInput} ${semanticClassNames.renameInput}`,
76
- value: editValue,
77
- onBlur: onCommitRename,
78
- onChange: (e) => onEditChange(e.target.value),
79
- onClick: (e) => e.stopPropagation(),
80
- onKeyDown: (e) => {
81
- if (e.key === "Enter") onCommitRename();
82
- if (e.key === "Escape") onCancelRename();
83
- }
84
- }
85
- ) : /* @__PURE__ */ jsx("span", { className: `${fileName} ${semanticClassNames.fileName}`, children: file.filename }),
86
- canDelete && /* @__PURE__ */ jsx(
87
- "button",
88
- {
89
- "aria-label": `Delete ${file.filename}`,
90
- className: `${fileDelete} ${semanticClassNames.fileDelete}`,
91
- type: "button",
92
- onClick: (e) => {
93
- e.stopPropagation();
94
- onDelete();
95
- },
96
- children: /* @__PURE__ */ jsx(Trash2, { size: 12 })
97
- }
98
- )
99
- ]
100
- }
101
- );
19
+ //#region src/CodeEditorModal.tsx
20
+ var SortableFileItem = ({ file, isActive, isEditing, editValue, canDelete, onSelect, onStartRename, onEditChange, onCommitRename, onCancelRename, onDelete }) => {
21
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: file.filename });
22
+ const style = {
23
+ transform: CSS.Transform.toString(transform),
24
+ transition
25
+ };
26
+ return /* @__PURE__ */ jsxs("div", {
27
+ className: `${fileItem({
28
+ active: isActive,
29
+ dragging: isDragging
30
+ })} ${semanticClassNames.fileItem} ${isActive ? semanticClassNames.fileItemActive : ""} ${isDragging ? semanticClassNames.fileItemDragging : ""}`.trim(),
31
+ ref: setNodeRef,
32
+ style,
33
+ onClick: onSelect,
34
+ onDoubleClick: onStartRename,
35
+ children: [
36
+ /* @__PURE__ */ jsx("span", {
37
+ className: `${fileDragHandle} ${semanticClassNames.fileDragHandle}`,
38
+ ...attributes,
39
+ ...listeners,
40
+ onClick: (e) => e.stopPropagation(),
41
+ children: /* @__PURE__ */ jsx(GripVertical, { size: 12 })
42
+ }),
43
+ /* @__PURE__ */ jsx(FileIcon, {
44
+ className: `${fileIcon} ${semanticClassNames.fileIcon}`,
45
+ filename: file.filename,
46
+ size: 14
47
+ }),
48
+ isEditing ? /* @__PURE__ */ jsx("input", {
49
+ autoFocus: true,
50
+ className: `${renameInput} ${semanticClassNames.renameInput}`,
51
+ value: editValue,
52
+ onBlur: onCommitRename,
53
+ onChange: (e) => onEditChange(e.target.value),
54
+ onClick: (e) => e.stopPropagation(),
55
+ onKeyDown: (e) => {
56
+ if (e.key === "Enter") onCommitRename();
57
+ if (e.key === "Escape") onCancelRename();
58
+ }
59
+ }) : /* @__PURE__ */ jsx("span", {
60
+ className: `${fileName} ${semanticClassNames.fileName}`,
61
+ children: file.filename
62
+ }),
63
+ canDelete && /* @__PURE__ */ jsx("button", {
64
+ "aria-label": `Delete ${file.filename}`,
65
+ className: `hjkryc11 ${semanticClassNames.fileDelete}`,
66
+ type: "button",
67
+ onClick: (e) => {
68
+ e.stopPropagation();
69
+ onDelete();
70
+ },
71
+ children: /* @__PURE__ */ jsx(Trash2, { size: 12 })
72
+ })
73
+ ]
74
+ });
102
75
  };
103
- const CodeEditorModal = ({
104
- files: initialFiles,
105
- onFilesChange,
106
- dismiss,
107
- colorScheme
108
- }) => {
109
- const [editFiles, setEditFiles] = useState(() => initialFiles.map((f) => ({ ...f })));
110
- const [activeFilename, setActiveFilename] = useState(initialFiles[0]?.filename ?? "");
111
- const [editingFilename, setEditingFilename] = useState(null);
112
- const [newFilenameInput, setNewFilenameInput] = useState("");
113
- const [dragActiveId, setDragActiveId] = useState(null);
114
- const containerRef = useRef(null);
115
- const editorRef = useRef(null);
116
- const languageCompartmentRef = useRef(null);
117
- const themeCompartmentRef = useRef(null);
118
- if (!languageCompartmentRef.current) languageCompartmentRef.current = new Compartment();
119
- if (!themeCompartmentRef.current) themeCompartmentRef.current = new Compartment();
120
- const onCodeChangeRef = useRef(void 0);
121
- const editFilesRef = useRef(editFiles);
122
- editFilesRef.current = editFiles;
123
- const activeFile = editFiles.find((f) => f.filename === activeFilename) ?? editFiles[0];
124
- onCodeChangeRef.current = (code) => {
125
- setEditFiles((prev) => prev.map((f) => f.filename === activeFilename ? { ...f, code } : f));
126
- };
127
- useEffect(() => {
128
- const container = containerRef.current;
129
- if (!container) return;
130
- const file = editFilesRef.current.find((f) => f.filename === activeFilename);
131
- if (!file) return;
132
- let cancelled = false;
133
- const lang = normalizeLanguage(file.language ?? getLanguageFromFilename(file.filename));
134
- const editor = new EditorView({
135
- parent: container,
136
- state: EditorState.create({
137
- doc: file.code,
138
- extensions: [
139
- history(),
140
- keymap.of([...defaultKeymap, ...historyKeymap, indentWithTab]),
141
- EditorView.updateListener.of((update) => {
142
- if (!update.docChanged) return;
143
- onCodeChangeRef.current?.(update.state.doc.toString());
144
- }),
145
- lineNumbers(),
146
- themeCompartmentRef.current.of(getThemeExtensions(colorScheme)),
147
- languageCompartmentRef.current.of([])
148
- ]
149
- })
150
- });
151
- editorRef.current = editor;
152
- (async () => {
153
- const extension = await loadLanguageExtension(lang);
154
- if (cancelled) return;
155
- editor.dispatch({
156
- effects: languageCompartmentRef.current.reconfigure(extension)
157
- });
158
- })();
159
- return () => {
160
- cancelled = true;
161
- editor.destroy();
162
- editorRef.current = null;
163
- };
164
- }, [activeFilename]);
165
- useEffect(() => {
166
- const editor = editorRef.current;
167
- if (!editor) return;
168
- editor.dispatch({
169
- effects: themeCompartmentRef.current.reconfigure(getThemeExtensions(colorScheme))
170
- });
171
- }, [colorScheme]);
172
- const handleDismiss = useCallback(() => {
173
- onFilesChange?.(editFiles);
174
- dismiss();
175
- }, [editFiles, onFilesChange, dismiss]);
176
- const handleAddFile = useCallback(() => {
177
- const name = `untitled-${editFiles.length + 1}.ts`;
178
- const newFile = {
179
- filename: name,
180
- code: "",
181
- language: "typescript"
182
- };
183
- setEditFiles((prev) => [...prev, newFile]);
184
- setActiveFilename(name);
185
- }, [editFiles.length]);
186
- const handleDeleteFile = useCallback(
187
- (filename) => {
188
- if (editFiles.length <= 1) return;
189
- const newFiles = editFiles.filter((f) => f.filename !== filename);
190
- setEditFiles(newFiles);
191
- if (activeFilename === filename) {
192
- setActiveFilename(newFiles[0]?.filename ?? "");
193
- }
194
- },
195
- [editFiles, activeFilename]
196
- );
197
- const handleRenameFile = useCallback(
198
- (oldName, newName) => {
199
- if (!newName.trim() || editFiles.some((f) => f.filename === newName && f.filename !== oldName)) {
200
- setEditingFilename(null);
201
- return;
202
- }
203
- setEditFiles(
204
- (prev) => prev.map(
205
- (f) => f.filename === oldName ? { ...f, filename: newName, language: void 0 } : f
206
- )
207
- );
208
- if (activeFilename === oldName) {
209
- setActiveFilename(newName);
210
- }
211
- setEditingFilename(null);
212
- },
213
- [editFiles, activeFilename]
214
- );
215
- const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 5 } }));
216
- const fileIds = useMemo(() => editFiles.map((f) => f.filename), [editFiles]);
217
- const handleDragEnd = useCallback(
218
- (event) => {
219
- const { active, over } = event;
220
- setDragActiveId(null);
221
- if (!over || active.id === over.id) return;
222
- const oldIndex = editFiles.findIndex((f) => f.filename === active.id);
223
- const newIndex = editFiles.findIndex((f) => f.filename === over.id);
224
- if (oldIndex === -1 || newIndex === -1) return;
225
- setEditFiles(arrayMove(editFiles, oldIndex, newIndex));
226
- },
227
- [editFiles]
228
- );
229
- const dragActiveFile = dragActiveId ? editFiles.find((f) => f.filename === dragActiveId) : null;
230
- const { className: portalThemeClassName } = usePortalTheme();
231
- const language = activeFile ? activeFile.language ?? getLanguageFromFilename(activeFile.filename) : "";
232
- return /* @__PURE__ */ jsxs("div", { className: `${modal} ${semanticClassNames.modal}`, children: [
233
- /* @__PURE__ */ jsxs("div", { className: `${modalTitlebar} ${semanticClassNames.modalTitlebar}`, children: [
234
- /* @__PURE__ */ jsx("span", { className: `${modalTitle} ${semanticClassNames.modalTitle}`, children: "Code Snippet" }),
235
- /* @__PURE__ */ jsx(
236
- "button",
237
- {
238
- className: `${modalIconButton} ${semanticClassNames.modalIconButton}`,
239
- type: "button",
240
- onClick: handleDismiss,
241
- children: /* @__PURE__ */ jsx(X, { size: 14 })
242
- }
243
- )
244
- ] }),
245
- /* @__PURE__ */ jsxs("div", { className: `${modalBody} ${semanticClassNames.modalBody}`, children: [
246
- /* @__PURE__ */ jsxs("div", { className: `${modalSidebar} ${semanticClassNames.modalSidebar}`, children: [
247
- /* @__PURE__ */ jsxs("div", { className: `${sidebarHeader} ${semanticClassNames.sidebarHeader}`, children: [
248
- /* @__PURE__ */ jsx("span", { children: "Files" }),
249
- /* @__PURE__ */ jsx(
250
- "button",
251
- {
252
- "aria-label": "Add file",
253
- className: `${sidebarAddButton} ${semanticClassNames.sidebarAddButton}`,
254
- type: "button",
255
- onClick: handleAddFile,
256
- children: /* @__PURE__ */ jsx(Plus, { size: 14 })
257
- }
258
- )
259
- ] }),
260
- /* @__PURE__ */ jsx("div", { className: `${fileList} ${semanticClassNames.fileList}`, children: /* @__PURE__ */ jsxs(
261
- DndContext,
262
- {
263
- collisionDetection: closestCenter,
264
- sensors,
265
- onDragCancel: () => setDragActiveId(null),
266
- onDragEnd: handleDragEnd,
267
- onDragStart: (event) => setDragActiveId(event.active.id),
268
- children: [
269
- /* @__PURE__ */ jsx(SortableContext, { items: fileIds, strategy: verticalListSortingStrategy, children: editFiles.map((file) => /* @__PURE__ */ jsx(
270
- SortableFileItem,
271
- {
272
- canDelete: editFiles.length > 1,
273
- editValue: newFilenameInput,
274
- file,
275
- isActive: file.filename === activeFilename,
276
- isEditing: editingFilename === file.filename,
277
- onCancelRename: () => setEditingFilename(null),
278
- onCommitRename: () => handleRenameFile(file.filename, newFilenameInput),
279
- onDelete: () => handleDeleteFile(file.filename),
280
- onEditChange: setNewFilenameInput,
281
- onSelect: () => setActiveFilename(file.filename),
282
- onStartRename: () => {
283
- setEditingFilename(file.filename);
284
- setNewFilenameInput(file.filename);
285
- }
286
- },
287
- file.filename
288
- )) }),
289
- typeof document !== "undefined" ? createPortal(
290
- /* @__PURE__ */ jsx(DragOverlay, { children: /* @__PURE__ */ jsx("div", { className: portalThemeClassName, style: { display: "contents" }, children: dragActiveFile ? /* @__PURE__ */ jsxs(
291
- "div",
292
- {
293
- className: `${fileItem()} ${semanticClassNames.fileItem} ${dragOverlay} ${semanticClassNames.dragOverlay}`,
294
- children: [
295
- /* @__PURE__ */ jsx(
296
- FileIcon,
297
- {
298
- className: `${fileIcon} ${semanticClassNames.fileIcon}`,
299
- filename: dragActiveFile.filename,
300
- size: 14
301
- }
302
- ),
303
- /* @__PURE__ */ jsx(
304
- "span",
305
- {
306
- className: `${fileName} ${semanticClassNames.fileName}`,
307
- children: dragActiveFile.filename
308
- }
309
- )
310
- ]
311
- }
312
- ) : null }) }),
313
- document.body
314
- ) : null
315
- ]
316
- }
317
- ) })
318
- ] }),
319
- /* @__PURE__ */ jsxs("div", { className: `${modalEditor} ${semanticClassNames.modalEditor}`, children: [
320
- /* @__PURE__ */ jsx("div", { className: `${breadcrumb} ${semanticClassNames.breadcrumb}`, children: /* @__PURE__ */ jsx("div", { className: `${breadcrumbLeft} ${semanticClassNames.breadcrumbLeft}`, children: activeFile && /* @__PURE__ */ jsxs(Fragment, { children: [
321
- /* @__PURE__ */ jsx(
322
- FileIcon,
323
- {
324
- className: `${fileIcon} ${semanticClassNames.fileIcon}`,
325
- filename: activeFile.filename,
326
- size: 14
327
- }
328
- ),
329
- /* @__PURE__ */ jsx(
330
- "span",
331
- {
332
- className: `${breadcrumbName} ${semanticClassNames.breadcrumbName}`,
333
- children: activeFile.filename
334
- }
335
- ),
336
- language && /* @__PURE__ */ jsx(
337
- "span",
338
- {
339
- className: `${breadcrumbLang} ${semanticClassNames.breadcrumbLang}`,
340
- children: language
341
- }
342
- )
343
- ] }) }) }),
344
- /* @__PURE__ */ jsx(
345
- "div",
346
- {
347
- className: `${editorContainer} ${semanticClassNames.editorContainer}`,
348
- ref: containerRef
349
- }
350
- )
351
- ] })
352
- ] })
353
- ] });
76
+ var CodeEditorModal = ({ files: initialFiles, onFilesChange, dismiss, colorScheme }) => {
77
+ const [editFiles, setEditFiles] = useState(() => initialFiles.map((f) => ({ ...f })));
78
+ const [activeFilename, setActiveFilename] = useState(initialFiles[0]?.filename ?? "");
79
+ const [editingFilename, setEditingFilename] = useState(null);
80
+ const [newFilenameInput, setNewFilenameInput] = useState("");
81
+ const [dragActiveId, setDragActiveId] = useState(null);
82
+ const containerRef = useRef(null);
83
+ const editorRef = useRef(null);
84
+ const languageCompartmentRef = useRef(null);
85
+ const themeCompartmentRef = useRef(null);
86
+ if (!languageCompartmentRef.current) languageCompartmentRef.current = new Compartment();
87
+ if (!themeCompartmentRef.current) themeCompartmentRef.current = new Compartment();
88
+ const onCodeChangeRef = useRef(void 0);
89
+ const editFilesRef = useRef(editFiles);
90
+ editFilesRef.current = editFiles;
91
+ const activeFile = editFiles.find((f) => f.filename === activeFilename) ?? editFiles[0];
92
+ onCodeChangeRef.current = (code) => {
93
+ setEditFiles((prev) => prev.map((f) => f.filename === activeFilename ? {
94
+ ...f,
95
+ code
96
+ } : f));
97
+ };
98
+ useEffect(() => {
99
+ const container = containerRef.current;
100
+ if (!container) return;
101
+ const file = editFilesRef.current.find((f) => f.filename === activeFilename);
102
+ if (!file) return;
103
+ let cancelled = false;
104
+ const lang = normalizeLanguage(file.language ?? getLanguageFromFilename(file.filename));
105
+ const editor = new EditorView({
106
+ parent: container,
107
+ state: EditorState.create({
108
+ doc: file.code,
109
+ extensions: [
110
+ history(),
111
+ keymap.of([
112
+ ...defaultKeymap,
113
+ ...historyKeymap,
114
+ indentWithTab
115
+ ]),
116
+ EditorView.updateListener.of((update) => {
117
+ if (!update.docChanged) return;
118
+ onCodeChangeRef.current?.(update.state.doc.toString());
119
+ }),
120
+ lineNumbers(),
121
+ themeCompartmentRef.current.of(getThemeExtensions(colorScheme)),
122
+ languageCompartmentRef.current.of([])
123
+ ]
124
+ })
125
+ });
126
+ editorRef.current = editor;
127
+ (async () => {
128
+ const extension = await loadLanguageExtension(lang);
129
+ if (cancelled) return;
130
+ editor.dispatch({ effects: languageCompartmentRef.current.reconfigure(extension) });
131
+ })();
132
+ return () => {
133
+ cancelled = true;
134
+ editor.destroy();
135
+ editorRef.current = null;
136
+ };
137
+ }, [activeFilename]);
138
+ useEffect(() => {
139
+ const editor = editorRef.current;
140
+ if (!editor) return;
141
+ editor.dispatch({ effects: themeCompartmentRef.current.reconfigure(getThemeExtensions(colorScheme)) });
142
+ }, [colorScheme]);
143
+ const handleDismiss = useCallback(() => {
144
+ onFilesChange?.(editFiles);
145
+ dismiss();
146
+ }, [
147
+ editFiles,
148
+ onFilesChange,
149
+ dismiss
150
+ ]);
151
+ const handleAddFile = useCallback(() => {
152
+ const name = `untitled-${editFiles.length + 1}.ts`;
153
+ const newFile = {
154
+ filename: name,
155
+ code: "",
156
+ language: "typescript"
157
+ };
158
+ setEditFiles((prev) => [...prev, newFile]);
159
+ setActiveFilename(name);
160
+ }, [editFiles.length]);
161
+ const handleDeleteFile = useCallback((filename) => {
162
+ if (editFiles.length <= 1) return;
163
+ const newFiles = editFiles.filter((f) => f.filename !== filename);
164
+ setEditFiles(newFiles);
165
+ if (activeFilename === filename) setActiveFilename(newFiles[0]?.filename ?? "");
166
+ }, [editFiles, activeFilename]);
167
+ const handleRenameFile = useCallback((oldName, newName) => {
168
+ if (!newName.trim() || editFiles.some((f) => f.filename === newName && f.filename !== oldName)) {
169
+ setEditingFilename(null);
170
+ return;
171
+ }
172
+ setEditFiles((prev) => prev.map((f) => f.filename === oldName ? {
173
+ ...f,
174
+ filename: newName,
175
+ language: void 0
176
+ } : f));
177
+ if (activeFilename === oldName) setActiveFilename(newName);
178
+ setEditingFilename(null);
179
+ }, [editFiles, activeFilename]);
180
+ const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 5 } }));
181
+ const fileIds = useMemo(() => editFiles.map((f) => f.filename), [editFiles]);
182
+ const handleDragEnd = useCallback((event) => {
183
+ const { active, over } = event;
184
+ setDragActiveId(null);
185
+ if (!over || active.id === over.id) return;
186
+ const oldIndex = editFiles.findIndex((f) => f.filename === active.id);
187
+ const newIndex = editFiles.findIndex((f) => f.filename === over.id);
188
+ if (oldIndex === -1 || newIndex === -1) return;
189
+ setEditFiles(arrayMove(editFiles, oldIndex, newIndex));
190
+ }, [editFiles]);
191
+ const dragActiveFile = dragActiveId ? editFiles.find((f) => f.filename === dragActiveId) : null;
192
+ const { className: portalThemeClassName } = usePortalTheme();
193
+ const language = activeFile ? activeFile.language ?? getLanguageFromFilename(activeFile.filename) : "";
194
+ return /* @__PURE__ */ jsxs("div", {
195
+ className: `${modal} ${semanticClassNames.modal}`,
196
+ children: [/* @__PURE__ */ jsxs("div", {
197
+ className: `${modalTitlebar} ${semanticClassNames.modalTitlebar}`,
198
+ children: [/* @__PURE__ */ jsx("span", {
199
+ className: `${modalTitle} ${semanticClassNames.modalTitle}`,
200
+ children: "Code Snippet"
201
+ }), /* @__PURE__ */ jsx("button", {
202
+ className: `${modalIconButton} ${semanticClassNames.modalIconButton}`,
203
+ type: "button",
204
+ onClick: handleDismiss,
205
+ children: /* @__PURE__ */ jsx(X, { size: 14 })
206
+ })]
207
+ }), /* @__PURE__ */ jsxs("div", {
208
+ className: `${modalBody} ${semanticClassNames.modalBody}`,
209
+ children: [/* @__PURE__ */ jsxs("div", {
210
+ className: `${modalSidebar} ${semanticClassNames.modalSidebar}`,
211
+ children: [/* @__PURE__ */ jsxs("div", {
212
+ className: `${sidebarHeader} ${semanticClassNames.sidebarHeader}`,
213
+ children: [/* @__PURE__ */ jsx("span", { children: "Files" }), /* @__PURE__ */ jsx("button", {
214
+ "aria-label": "Add file",
215
+ className: `${sidebarAddButton} ${semanticClassNames.sidebarAddButton}`,
216
+ type: "button",
217
+ onClick: handleAddFile,
218
+ children: /* @__PURE__ */ jsx(Plus, { size: 14 })
219
+ })]
220
+ }), /* @__PURE__ */ jsx("div", {
221
+ className: `${fileList} ${semanticClassNames.fileList}`,
222
+ children: /* @__PURE__ */ jsxs(DndContext, {
223
+ collisionDetection: closestCenter,
224
+ sensors,
225
+ onDragCancel: () => setDragActiveId(null),
226
+ onDragEnd: handleDragEnd,
227
+ onDragStart: (event) => setDragActiveId(event.active.id),
228
+ children: [/* @__PURE__ */ jsx(SortableContext, {
229
+ items: fileIds,
230
+ strategy: verticalListSortingStrategy,
231
+ children: editFiles.map((file) => /* @__PURE__ */ jsx(SortableFileItem, {
232
+ canDelete: editFiles.length > 1,
233
+ editValue: newFilenameInput,
234
+ file,
235
+ isActive: file.filename === activeFilename,
236
+ isEditing: editingFilename === file.filename,
237
+ onCancelRename: () => setEditingFilename(null),
238
+ onCommitRename: () => handleRenameFile(file.filename, newFilenameInput),
239
+ onDelete: () => handleDeleteFile(file.filename),
240
+ onEditChange: setNewFilenameInput,
241
+ onSelect: () => setActiveFilename(file.filename),
242
+ onStartRename: () => {
243
+ setEditingFilename(file.filename);
244
+ setNewFilenameInput(file.filename);
245
+ }
246
+ }, file.filename))
247
+ }), typeof document !== "undefined" ? createPortal(/* @__PURE__ */ jsx(DragOverlay, { children: /* @__PURE__ */ jsx("div", {
248
+ className: portalThemeClassName,
249
+ style: { display: "contents" },
250
+ children: dragActiveFile ? /* @__PURE__ */ jsxs("div", {
251
+ className: `${fileItem()} ${semanticClassNames.fileItem} ${dragOverlay} ${semanticClassNames.dragOverlay}`,
252
+ children: [/* @__PURE__ */ jsx(FileIcon, {
253
+ className: `${fileIcon} ${semanticClassNames.fileIcon}`,
254
+ filename: dragActiveFile.filename,
255
+ size: 14
256
+ }), /* @__PURE__ */ jsx("span", {
257
+ className: `${fileName} ${semanticClassNames.fileName}`,
258
+ children: dragActiveFile.filename
259
+ })]
260
+ }) : null
261
+ }) }), document.body) : null]
262
+ })
263
+ })]
264
+ }), /* @__PURE__ */ jsxs("div", {
265
+ className: `${modalEditor} ${semanticClassNames.modalEditor}`,
266
+ children: [/* @__PURE__ */ jsx("div", {
267
+ className: `${breadcrumb} ${semanticClassNames.breadcrumb}`,
268
+ children: /* @__PURE__ */ jsx("div", {
269
+ className: `${breadcrumbLeft} ${semanticClassNames.breadcrumbLeft}`,
270
+ children: activeFile && /* @__PURE__ */ jsxs(Fragment, { children: [
271
+ /* @__PURE__ */ jsx(FileIcon, {
272
+ className: `hjkrycf ${semanticClassNames.fileIcon}`,
273
+ filename: activeFile.filename,
274
+ size: 14
275
+ }),
276
+ /* @__PURE__ */ jsx("span", {
277
+ className: `hjkryc16 ${semanticClassNames.breadcrumbName}`,
278
+ children: activeFile.filename
279
+ }),
280
+ language && /* @__PURE__ */ jsx("span", {
281
+ className: `hjkryc17 ${semanticClassNames.breadcrumbLang}`,
282
+ children: language
283
+ })
284
+ ] })
285
+ })
286
+ }), /* @__PURE__ */ jsx("div", {
287
+ className: `${editorContainer} ${semanticClassNames.editorContainer}`,
288
+ ref: containerRef
289
+ })]
290
+ })]
291
+ })]
292
+ });
354
293
  };
355
- const CodeSnippetEditRenderer = ({
356
- files,
357
- onFilesChange
358
- }) => {
359
- const { className: portalClassName } = usePortalTheme();
360
- const colorScheme = useColorScheme();
361
- const handleEdit = useCallback(() => {
362
- presentDialog({
363
- content: ({ dismiss }) => /* @__PURE__ */ jsx(
364
- CodeEditorModal,
365
- {
366
- colorScheme,
367
- dismiss,
368
- files,
369
- onFilesChange
370
- }
371
- ),
372
- className: codeSnippetDialogPopup,
373
- portalClassName,
374
- theme: colorScheme,
375
- showCloseButton: false,
376
- clickOutsideToDismiss: false
377
- });
378
- }, [files, onFilesChange, portalClassName, colorScheme]);
379
- return /* @__PURE__ */ jsxs("div", { className: `${editContainer} ${semanticClassNames.editContainer}`, children: [
380
- /* @__PURE__ */ jsx(CodeSnippetRenderer, { files }),
381
- /* @__PURE__ */ jsx(
382
- "button",
383
- {
384
- "aria-label": "Edit code snippet",
385
- className: `${editOverlay} ${semanticClassNames.editOverlay}`,
386
- type: "button",
387
- onClick: handleEdit,
388
- children: /* @__PURE__ */ jsxs("span", { className: `${editLabel} ${semanticClassNames.editLabel}`, children: [
389
- /* @__PURE__ */ jsx(Pencil, { size: 14 }),
390
- "Edit"
391
- ] })
392
- }
393
- )
394
- ] });
294
+ //#endregion
295
+ //#region src/CodeSnippetEditRenderer.tsx
296
+ var CodeSnippetEditRenderer = ({ files, onFilesChange }) => {
297
+ const { className: portalClassName } = usePortalTheme();
298
+ const colorScheme = useColorScheme();
299
+ const handleEdit = useCallback(() => {
300
+ presentDialog({
301
+ content: ({ dismiss }) => /* @__PURE__ */ jsx(CodeEditorModal, {
302
+ colorScheme,
303
+ dismiss,
304
+ files,
305
+ onFilesChange
306
+ }),
307
+ className: codeSnippetDialogPopup,
308
+ portalClassName,
309
+ theme: colorScheme,
310
+ showCloseButton: false,
311
+ clickOutsideToDismiss: false
312
+ });
313
+ }, [
314
+ files,
315
+ onFilesChange,
316
+ portalClassName,
317
+ colorScheme
318
+ ]);
319
+ return /* @__PURE__ */ jsxs("div", {
320
+ className: `${editContainer} ${semanticClassNames.editContainer}`,
321
+ children: [/* @__PURE__ */ jsx(CodeSnippetRenderer, { files }), /* @__PURE__ */ jsx("button", {
322
+ "aria-label": "Edit code snippet",
323
+ className: `${editOverlay} ${semanticClassNames.editOverlay}`,
324
+ type: "button",
325
+ onClick: handleEdit,
326
+ children: /* @__PURE__ */ jsxs("span", {
327
+ className: `${editLabel} ${semanticClassNames.editLabel}`,
328
+ children: [/* @__PURE__ */ jsx(Pencil, { size: 14 }), "Edit"]
329
+ })
330
+ })]
331
+ });
395
332
  };
396
- const r = createContext(null);
333
+ //#endregion
334
+ //#region ../../node_modules/.pnpm/@lexical+react@0.41.0_react-dom@19.2.4_react@19.2.4__react@19.2.4_yjs@13.6.29/node_modules/@lexical/react/LexicalComposerContext.prod.mjs
335
+ /**
336
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
337
+ *
338
+ * This source code is licensed under the MIT license found in the
339
+ * LICENSE file in the root directory of this source tree.
340
+ *
341
+ */
342
+ var r = createContext(null);
397
343
  function o() {
398
- const n = useContext(r);
399
- return null == n && (function(n2, ...e) {
400
- const r2 = new URL("https://lexical.dev/docs/error"), t = new URLSearchParams();
401
- t.append("code", n2);
402
- for (const n3 of e) t.append("v", n3);
403
- throw r2.search = t.toString(), Error(`Minified Lexical error #${n2}; visit ${r2.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`);
404
- })(8), n;
344
+ const n = useContext(r);
345
+ return n ?? function(n, ...e) {
346
+ const r = new URL("https://lexical.dev/docs/error"), t = new URLSearchParams();
347
+ t.append("code", n);
348
+ for (const n of e) t.append("v", n);
349
+ throw r.search = t.toString(), Error(`Minified Lexical error #${n}; visit ${r.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`);
350
+ }(8), n;
405
351
  }
406
- const CodeSnippetEditDecorator = ({ nodeKey, files }) => {
407
- const [editor] = o();
408
- const onFilesChange = useCallback(
409
- (newFiles) => {
410
- editor.update(() => {
411
- const node = $getNodeByKey(nodeKey);
412
- if ($isCodeSnippetNode(node)) {
413
- node.setFiles(newFiles);
414
- }
415
- });
416
- },
417
- [editor, nodeKey]
418
- );
419
- return /* @__PURE__ */ jsx(CodeSnippetEditRenderer, { files, onFilesChange });
352
+ //#endregion
353
+ //#region src/CodeSnippetEditDecorator.tsx
354
+ var CodeSnippetEditDecorator = ({ nodeKey, files }) => {
355
+ const [editor] = o();
356
+ return /* @__PURE__ */ jsx(CodeSnippetEditRenderer, {
357
+ files,
358
+ onFilesChange: useCallback((newFiles) => {
359
+ editor.update(() => {
360
+ const node = $getNodeByKey(nodeKey);
361
+ if ($isCodeSnippetNode(node)) node.setFiles(newFiles);
362
+ });
363
+ }, [editor, nodeKey])
364
+ });
420
365
  };
421
- const _CodeSnippetEditNode = class _CodeSnippetEditNode extends CodeSnippetNode {
422
- static clone(node) {
423
- return new _CodeSnippetEditNode(node.__files, node.__key);
424
- }
425
- static importJSON(serializedNode) {
426
- return new _CodeSnippetEditNode(serializedNode.files);
427
- }
428
- decorate(_editor, _config) {
429
- return createElement(CodeSnippetEditDecorator, {
430
- nodeKey: this.__key,
431
- files: this.__files
432
- });
433
- }
366
+ //#endregion
367
+ //#region src/nodes/CodeSnippetEditNode.ts
368
+ var CodeSnippetEditNode = class CodeSnippetEditNode extends CodeSnippetNode {
369
+ static clone(node) {
370
+ return new CodeSnippetEditNode(node.__files, node.__key);
371
+ }
372
+ static importJSON(serializedNode) {
373
+ return new CodeSnippetEditNode(serializedNode.files);
374
+ }
375
+ decorate(_editor, _config) {
376
+ return createElement(CodeSnippetEditDecorator, {
377
+ nodeKey: this.__key,
378
+ files: this.__files
379
+ });
380
+ }
434
381
  };
435
- __publicField(_CodeSnippetEditNode, "commandItems", [
436
- {
437
- title: "Code Snippet",
438
- icon: createElement(FileCode, { size: 20 }),
439
- description: "Multi-file code snippet with tabs",
440
- keywords: ["code", "snippet", "files", "tabs"],
441
- section: "MEDIA",
442
- placement: ["slash", "toolbar"],
443
- group: "insert",
444
- onSelect: (editor) => {
445
- editor.update(() => {
446
- $insertNodes([
447
- $createCodeSnippetEditNode([
448
- { filename: "index.ts", code: "", language: "typescript" }
449
- ])
450
- ]);
451
- });
452
- }
453
- }
454
- ]);
455
- let CodeSnippetEditNode = _CodeSnippetEditNode;
382
+ _defineProperty(CodeSnippetEditNode, "commandItems", [{
383
+ title: "Code Snippet",
384
+ icon: createElement(FileCode, { size: 20 }),
385
+ description: "Multi-file code snippet with tabs",
386
+ keywords: [
387
+ "code",
388
+ "snippet",
389
+ "files",
390
+ "tabs"
391
+ ],
392
+ section: "MEDIA",
393
+ placement: ["slash", "toolbar"],
394
+ group: "insert",
395
+ onSelect: (editor) => {
396
+ editor.update(() => {
397
+ $insertNodes([$createCodeSnippetEditNode([{
398
+ filename: "index.ts",
399
+ code: "",
400
+ language: "typescript"
401
+ }])]);
402
+ });
403
+ }
404
+ }]);
456
405
  function $createCodeSnippetEditNode(files) {
457
- return new CodeSnippetEditNode(files);
406
+ return new CodeSnippetEditNode(files);
458
407
  }
459
408
  function $isCodeSnippetEditNode(node) {
460
- return node instanceof CodeSnippetEditNode;
409
+ return node instanceof CodeSnippetEditNode;
461
410
  }
462
- const codeSnippetNodes = [CodeSnippetNode];
463
- const codeSnippetEditNodes = [CodeSnippetEditNode];
464
- export {
465
- $createCodeSnippetEditNode,
466
- E as $createCodeSnippetNode,
467
- $isCodeSnippetEditNode,
468
- $isCodeSnippetNode,
469
- CODE_SNIPPET_BLOCK_TRANSFORMER,
470
- CodeSnippetEditNode,
471
- CodeSnippetEditRenderer,
472
- CodeSnippetNode,
473
- CodeSnippetRenderer,
474
- codeSnippetEditNodes,
475
- codeSnippetNodes
476
- };
411
+ //#endregion
412
+ //#region src/nodes/index.ts
413
+ var codeSnippetNodes = [CodeSnippetNode];
414
+ var codeSnippetEditNodes = [CodeSnippetEditNode];
415
+ //#endregion
416
+ export { $createCodeSnippetEditNode, $createCodeSnippetNode, $isCodeSnippetEditNode, $isCodeSnippetNode, CODE_SNIPPET_BLOCK_TRANSFORMER, CodeSnippetEditNode, CodeSnippetEditRenderer, CodeSnippetNode, CodeSnippetRenderer, codeSnippetEditNodes, codeSnippetNodes };